为什么编译器在这种情况下没有省略副本构造

why compiler is not eliding away copy construction in this case

本文关键字:副本 编译器 这种情况下 为什么      更新时间:2023-10-16
class test
{
public:
    int data;
    test(int var = 0):data(var){cout<<"constructor"<<endl;}
    ~test(){ cout<<"destructor"<<endl; }
    test(const test& var)
    {
        cout<<"copy constructor"<<endl;
        this->data = var.data;
    }
    test& operator=( const test& var)
    {
        cout<<"assignment op"<<endl;
        this->data = var.data;
        return *this;
    }
};

test passByref_returnByVal(test& obj)    
{    
    return obj;    
}

int main()
{
    test o1(5);
    test o2 = passByref_returnByVal(o1);
    cout<<"=========================="<<endl;
    test o3;
    o3 = passByref_returnByVal(o1);   
}

输出:

constructor
copy constructor
constructor
copy constructor
assignment op
destructor

在给定的示例中,对象o2是直接复制构造的,而不使用任何临时变量。

但是在第二种情况下,我希望o3被分配函数的返回值,首先使用复制构造函数创建一个临时值,然后调用赋值运算符进行值赋值。

我的问题是,当我的分配操作员参考时,这个临时需要什么。我找到了相关的问题,但他们没有回答这个问题。

test o3;

将导致调用构造函数来创建对象。 C++不是 Java,其中对象类型声明仅声明引用但不实例化对象。

test passByref_returnByVal(test& obj) {....}

导致复制构造函数调用,因为当您在其中执行return obj;编译器需要创建一个临时对象,因为该函数的返回类型是test(而不是test&test*)。

最后,因为o3已经存在了

test o3;

声明,调用赋值运算符以将 passByref_returnByVal 的返回值分配给已经存在的o3

所以复制构造函数调用发生在passByref_returnByVal,而不是在你的operator=中。