简 述: 分析 C++ Class 的六个特殊成员函数 wiki ,并且手动实现一番;
- 默认构造函数
- 析构函数
- 复制构造函数
- 复制赋值运算符
- 移动构造函数
- 移动赋值运算符
文章目录
- 原理
- 代码
- 系列
本文初发于 “偕臧的小站”,同步转载于此。
原理
特殊成员函数是类(或结构)成员函数,在某些情况下,编译器会自动为你生成。
- default constructor: 通常没有参数,但可以具有带默认值的参数。
- destructor: 销毁对象的前一刻执行清理
- copy constructor: 对新建的的对象进行初始化,形参是
const T&
- copy assignment constructor: 对已有的对象进行赋值,形参是
const T&
- move constructor: 对新建的的对象进行初始化,形参是
T &&
- move assignment constructor: 对已有的对象进行赋值,形参是
T &&
-
move 的函数相对于 copy 的函数没有
const
-
copy 是属完整的再复制拷贝一份;move 是对将亡的右值进行指针互换、节省空间提升效率
-
”复制 / 移动构造函数“ 属于新建对象,无需判断两者是否相等;”复制 / 移动赋值运算符“ 属于已有的对象进行赋值,赋值时需要先判断两者是否相等。
-
若有深拷贝时,”复制 / 移动赋值运算符“ 除了判断相等、数值是否有效;在拷贝字节前,还要先释放旧资源
-
只有当类存储了需要释放的系统资源的句柄,或拥有其指向的内存的指针时,你才需要定义自定义 ”析构函数“
-
三五法则 cppreference.com
代码
💻 win10 22H2
📎 Visual Studio 2019
📎 C++17
/******************************************************************** Copyright (c) 2022~2023 XMuli All rights reserved.* Description: C++ 类的六个特殊成员函数******************************************************************/
#pragma once
#include <iostream>
#include <utility>
using namespace std;class A
{
public:A() : m_ptr(nullptr) {std::cout << "default constructor" << endl;}A(const char* s) : m_ptr(nullptr) {std::cout << "no-default-val constructor" << endl;if (s) {auto n = std::strlen(s) + 1;m_ptr = new char[n];std::memcpy(m_ptr, s, n);}}A(const A& other): m_ptr(nullptr) {std::cout << "copy constructor" << endl;if (other.m_ptr) {auto n = std::strlen(other.m_ptr) + 1;m_ptr = new char[n];std::memcpy(m_ptr, other.m_ptr, n);}}A& operator = (const A& other) {std::cout << "copy assignment constructor" << endl;if (this != &other) {delete[] m_ptr; // Free the existing resource. 重点 !!!if (other.m_ptr != nullptr) {auto n = std::strlen(other.m_ptr) + 1;m_ptr = new char[n];std::memcpy(m_ptr, other.m_ptr, n);}}return *this;}A(A&& other) noexcept // 行参无 const: m_ptr(nullptr) {std::cout << "move constructor" << endl;if (other.m_ptr)m_ptr = std::move(other.m_ptr);other.m_ptr = nullptr;}A& operator=(A&& other) noexcept { // 行参无 conststd::cout << "move assignment constructor" << endl;if (this != &other) {delete[] m_ptr; // Free the existing resource.if (other.m_ptr)m_ptr = std::move(other.m_ptr);other.m_ptr = nullptr;}return *this;}~A() {std::cout << "destructor" << endl;if (m_ptr)delete[] m_ptr;}private:char* m_ptr;
};A fn() {A t("A fun()");return t;
}int main()
{A a1("a1"); // default constructorA a2(a1); // copy constructorA a3 = a1; // copy constructora1 = a3; // copy assignment constructorstd::cout << "----------------------------\n\n";//fn(); // function returning a A objectA a5 = std::move(a1); // move constructorA a6; // default constructora6 = std::move(a1); // move assignment constructorstd::cout << "Hello World!\n";return 0;
}/*************************** 运行结果 *******************************
* no-default-val constructor
copy constructor
copy constructor
copy assignment constructor
----------------------------move constructor
default constructor
move assignment constructor
Hello World!
destructor
destructor
destructor
destructor
destructor******************************************************************/
拷贝构造函数是 A a2(a1);
形式,还可以是 A a3 = a1;
这种形式。关键看是新创建对象还是已有的对象赋值。move 的函数赋值,借助 std::move()
将左值转换为右值。
系列
QtExamples 的 SpecialMembers.h
欢迎 star
⭐ 和 fork
🍴这个系列的 C++ / QT / DTK
学习,附学习由浅入深的目录。