首页 > 解决方案 > 复制和移动构造函数

问题描述

具有以下代码:

#include <iostream>
#include <vector>
using namespace std;

class CIntPtr {
public:
    int* ptr;
public:
    CIntPtr() {
        // Default constructor
        cout << "Calling Default constructor\n";
        ptr = new int;
    }

    CIntPtr(const CIntPtr& obj) {
        // Copy Constructor
        // copy of object is created
        this->ptr = new int;
        // Deep copying
        cout << "Calling Copy constructor\n";
    }

    CIntPtr(CIntPtr&& obj) {
        // Move constructor
        // It will simply shift the resources,
        // without creating a copy.
        cout << "Calling Move constructor\n";
        this->ptr = obj.ptr;
        obj.ptr = NULL;
    }

    ~CIntPtr() {
        // Destructor
        cout << "Calling Destructor\n";
        delete ptr;
    }

};

CIntPtr returnCIntPtr(CIntPtr a) {
    *a.ptr += 2;
    return a;
}

int main() {

    CIntPtr foo;
    returnCIntPtr(foo);
    
    return 0;
}

调用了复制移动构造函数。为什么还要调用move ctor?既然我们将左值作为 f-ction 参数传递,它不应该只是调用的复制 ctor吗?什么时候可以在这段代码中调用 move ctor?

标签: c++

解决方案


在 function 的return 语句(即)中调用 move 构造return a;函数returnCIntPtr

从局部变量和参数自动移动

如果表达式是一个(可能是带括号的)id 表达式,它命名一个变量,其类型是

  • 非易失性对象类型或
  • a non-volatile rvalue reference to object type (since C++20)

并且声明了该变量

  • 在体内或
  • 作为参数

最里面的封闭函数或 lambda 表达式,

然后执行两次重载决议以选择用于初始化返回值的构造函数:or, for co_return, to select the overload of promise.return_value() (since C++20)

  • 首先好像表达式是一个右值表达式(因此它可以选择移动构造函数),并且
    • 如果第一个重载决议失败或
  • 然后像往常一样执行重载决议,将表达式视为左值(因此它可以选择复制构造函数)。

a将首先尝试将其作为 rvalue-expression 复制到返回值,然后选择移动构造函数。


推荐阅读