在 C++ 中按值传递期间不使用复制构造函数

Copy constructor not used during pass by value in C++

class A {
    int x;
public:
    A() { cout << "\t A() \n"; }
    A(int _x): x(_x) { cout << "\t A(int) \n"; }
    A(const A& other): x(other.x) { cout << "\t A(const A&) \n"; }
    A(A&& other): x(std::move(other.x)) { cout << "\t A(A&&) \n"; }
    A& operator=(const A& other) { x = other.x; cout << "\t operator=() \n"; return *this; }
};

void func_1(A obj) {
    cout << "func_1\n";
}

A func_7(const A& obj) {
    cout << "func_7\n";
    return obj;
}

int main() {

    A obj_1;                        // stdout: "A()"                    [OK]
    A obj_2 = 10;                   // stdout: "A(int)"                 [OK]
    A obj_3 = obj_2;                // stdout: "A(const A&)"            [OK]
    A obj_4 = std::move(obj_3);     // stdout: "A(A&&)"                 [OK]
    obj_4 = obj_2;                  // stdout: "operator=()"            [OK]

    func_1(obj_1);                  // stdout: "A(const A&) \n func_1"  [OK]
    func_1(A(5));                   // stdout: "A(int) \n func_1"       [!?] Copy constructor?
    func_1(5);                      // stdout: "A(int) \n func_1"       [!?] Copy constructor?
    A obj_7 = func_7(obj_2);        // stdout: "func_7 \n A(const A&)"  [!?] Copy constructor?

    return 0;
}

对于 func_1(A(5));,我预计输出为 A(int) \n A(const A&) \n func_1,因为我们按值传递 A(5),因此传递的对象应该被复制到参数中。 func_1(5);.

同样

对于 A obj_7 = func_7(obj_2);,我预计输出是 func_7 \n A(const A&) \n A(const A&) 因为我们正在 returning 一个对象,所以应该先将对象复制到堆栈上,然后复制构造函数将用于使用 returned 对象声明 obj_7

我是不是漏掉了什么?我知道 return 价值优化,但我认为这不会适用于我们这里的两个功能。

For func_1(A(5));, I expected the output to be A(int) \n A(const A&) \n func_1 because we are passing A(5) by value so the passed object should be copied to the parameter.

你误会了。 A(5) 是相同类型的纯右值,因此临时对象不会被具体化,而是使用其初始化器来初始化本应由非具体化临时对象初始化的参数。

Similarly for func_1(5);.

class 有一个接受整数的隐式转换构造函数。你传递一个整数;转换构造函数用于初始化参数。

For A obj_7 = func_7(obj_2);, I expected the output to be func_7 \n A(const A&) \n A(const A&) because we are returning an object so that object should be copied on the stack first and then the copy constructor will be used to declare obj_7 using the returned object.

原因与第一种情况类似。函数调用是纯右值。

func_1(A(5)); 的情况下,不会调用 copy ctor,因为 A(5) 是一个 rvalue(又名临时)。 copy ctor 仅在右侧的值是 lvalue(也就是具有专用内存位置的值)时调用。

而在 A obj_7 = func_7(obj_2); 的情况下,copy ctor 只会被调用一次以构造 obj_7。当您将 obj_2 作为 左值引用 传递给 func_7 时,它不会被调用。 func_7的参数是参考。不是新对象。所以不需要调用 copy ctor