Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么复制构造函数要调用两次?_C++ - Fatal编程技术网

C++ 为什么复制构造函数要调用两次?

C++ 为什么复制构造函数要调用两次?,c++,C++,在下面的代码中,复制构造函数被调用了两次,为什么 #include <iostream> using namespace std; class A { int X; public: A() { cout << "Simple Constructor" << endl; } A(int b) :X(b) { cout << "Constructor &quo

在下面的代码中,复制构造函数被调用了两次,为什么

#include <iostream>
using namespace std;
class A {
    int X;
public:
    A() {
        cout << "Simple Constructor" << endl;
    }
    A(int b) :X(b) {
        cout << "Constructor " << X << endl;
    }
    A(const A& obj) :X(obj.X) {
        cout << "Copy Constructor " << endl;
    }
    ~A() {
        cout << "Destructor " << X << endl;
    }
};
A fun(A obj) {
    cout << "Fun" << endl;
    return obj;
}
int main() {
    A obj(10);
    obj = fun(obj); // here is confusion
    cout << "End" << endl;
    return 0;
}

我想可能是因为临时对象而调用了第二个复制构造函数。

第一个复制构造函数调用是在调用fun(obj)时执行的。您通过值传递obj,因此它被复制,并在函数内部使用该副本。 下一次复制是在返回obj时执行的。它也是通过值返回的,因此会再次复制它

我不知道你的意图是什么。如果要修改函数中的对象,最好通过引用传递它并使函数无效:

void fun(A& obj) {
    cout << "Fun" << endl;
}
这样可以防止对复制构造函数的两个调用

编辑:

如果您想知道为什么不执行返回值优化,您应该知道这是可选行为,这是标准允许的编译器行为。首先,您应该确保允许您的编译器优化代码(例如,您不使用调试构建),然后确保它实际支持RVO。最后,您应该考虑在这种情况下,优化是否真的有意义。对象内部只有一个int,所以它的大小为基类型。
关于优化,需要记住的一点是,它可以执行,但编译器是决定是否执行它的人。

fun()
中,您获取了一个副本并返回了一个副本,那么您为什么要问?@πάνταῥεῖ 是否返回复制到临时对象的对象?然后函数的对象和临时对象销毁?@πάνταῥεῖ 好的,但是编译器忽略了临时对象。并且不要为临时对象调用复制构造函数。。你能告诉我编译器在哪里调用了临时对象的复制构造函数或析构函数吗?如果你想进一步挖掘,它会被调用。顺便说一句,最近也有同样的问题。但是第二个副本,复制到临时对象?它会从obj(在return语句中)复制到临时对象,然后调用默认赋值运算符(在obj=fun…)它将常量引用作为参数。
void fun(A& obj) {
    cout << "Fun" << endl;
}
fun(obj);