C++类的构造重载、赋值重载与右值引用

为什么要重载运算符“=”和拷贝构造函数?

  1. 为了给类赋予新的能力的同时保持语义。比如之前文章提到的迭代器(iterator)重载自加操作符,就是为了保持语义;
  2. 类的职责多样,有的类的拷贝过程默认拷贝构造函数无法满足,需要定制(比如深拷贝)。

拷贝构造/移动构造函数

拷贝构造函数重载相信我们已经见过太多,无非就是这样的形式(构造函数多了个常量引用作为参数):

Foo& Foo::Foo(const Foo &f);

但是C++11带来了移动语义,我们可以定义移动构造函数,构造函数接收一个右值引用的时候,就会调用它。示例如下:

Foo& Foo::Foo(Foo &&f); // 这里通常去掉const,因为移动语义通常意味着要“偷”资源。
int main()
{
    Foo f1{...}; // 省略掉了初始化
    Foo f2(f1);  // 这里调用拷贝构造函数
    Foo f3(std::move(f1)); // 这里将调用移动构造函数,因为std::move返回了f1的右值引用,f1成为将亡值
    
    // 将亡值f1被释放或被重新分配资源
    // ...
    // ...

    return 0;
}

赋值/移动赋值函数

思路基本和拷贝构造/移动构造函数之间的关系差不多,下面是函数声明:

Foo& operator=(const Foo& f); // 这里返回reference to this,性能比返回拷贝要好些
Foo& operator=(Foo &&f);      // 里面要进行“偷”资源的操作,并且一定要传入右值引用才能启用
posted @ 2020-02-29 21:02  joeyzzz  阅读(1031)  评论(0编辑  收藏  举报