1. 构造函数:

(1)成员初始化顺序

成员初始化顺序必须与他们在类定义中的出现顺序一致,而不是在初始值中出现的顺序

(2)必须初始化的情况:

const成员和引用成员必须初始化

2. 默认构造函数

(1)编译器帮助

不定义构造函数时,编译器自动产生默认构造函数

(2)重定义警告

不可以同时定义有参和无参的默认构造函数

3. 复制构造函数

调用复制构造函数的三种情况

1) 定义新对象以老对象作为复制

2) 以函数形式参数传入类的对象

3) 函数的返回值是类的对象

4. 析构函数

(1)功能

自动调用完成清理工作 调用后对象消失 内存释放

(2)特性

无函数类型 无参数 不能重载

5. 移动构造函数

(1)左值与右值引用

#include <iostream>
using namespace std;

int main() {
    float n = 6;
    float &lr_n = n; //  左值引用

    float &&rr_n = n * n; //    右值表达式绑定到右值引用

    //float &&rr_n2 = n;    错误,右值引用不能绑定到左值
//
    float &&rr_n2 = std::move(n); //将n转化为右值

    return 0;
}

(2)定义移动构造函数

a. 函数签名

移动构造函数的参数是右值引用

b. 函数体实现

在函数体中将资源从被引用的对象转向引用的对象;如果类中有指针成员,需将指针置空,避免被释放两次

c. 注意事项

要确保移动后的源对象处于有效但可能未定义的状态,这样源对象的析构函数能正确执行且不会发生错误

class Myclass{
    int *data;
    int size;
  public:
     Myclass(Myclass&& other){
            data=other.data;
            size=other.size;
            other.data=nullptr;
            other.size=0;
            }
  };

(3)调用移动构造函数

a. 返回值优化场景

当函数返回一个局部对象时,编译器可能会利用移动构造函数来避免不必要的复制

Myclass createObject(){
       Myclass temp;
        初始化temp
//
       return temp;
}

int main()
{
       Myclass newObj=createObject();
       //这里会调用移动构造函数将createObject函数中的临时对象temp的资源移动到newObj
       return 0;
}

b. 使用std::move显示调用

若有一个左值(可以取地址的对象),但想将其当做右值来使用,从而调用移动构造函数,可以使用std::move函数。调用std::move后,原来的对象可能处于一种被移动后的不确定状态

Myclass Obj1;//  初始化Obj1
Myclass Obj2=std::move(Obj1);
// 移动构造函数将Obj1的资源移动到Obj2,Obj1的状态可能不符合预期,在使用Obj1之前可能需要重
新初始化

6. default、delete函数

=default:要求编译器生成默认或复制构造函数=delete:要求编译器删除指定函数,除析构函数之外均可以删除