关于C++中的构造函数和赋值运算符

6

我只是创建了一个类,像这样:

class GreatClass
{
public:
    GreatClass(){cout<<"Default Constructor Called!\n";}
    GreatClass(GreatClass &gc){cout<<"Copy Constructor Called!\n";}
    GreatClass(const GreatClass &gc){cout<<"Copy Constructor (CONST) Called!\n";}
    ~GreatClass(){cout<<"Destructor Called.\n";}
    GreatClass& operator=(GreatClass& gc){cout<<"Assign Operator Called!";return gc;}
    const GreatClass& operator=(const GreatClass& gc){cout<<"Assign Operator (CONST) Called!";return gc;}
};

GreatClass f(GreatClass gc)
{
    return gc;
}

在main()函数中,有两个版本:
版本 #1:
int main()
{
    GreatClass g1;
    GreatClass G = f(g1);
}

版本 #2:

int main()
{
    GreatClass g1;
    f(g1);
}

它们都生成相同的输出:

Default Constructor Called!
Copy Constructor Called!
Copy Constructor Called!
Destructor Called.
Destructor Called.
Destructor Called.

我不明白为什么我把f(g1)赋值给G时,没有任何反应。在这一点上调用了哪个构造函数或运算符?
谢谢。

4
复制省略是正在发生的事情。如果您使用的是GCC编译器,请尝试使用“-fno-elide-constructors”编译选项。 - Andy Prowl
我想你困惑的部分可能是为什么不使用operator=。这是由标准指定的。形如A a2 = a1;的内容是复制初始化,使用的是复制构造函数(而不是赋值运算符)。也可能会发生复制省略。 - huskerchad
1个回答

13
编译器实现允许在某些情况下省略/删除复制构造函数调用,你所指定的示例是这种情况的一个很好的使用案例。不需要创建临时对象并将其复制到目标对象中,而是直接在目标对象中创建对象,并删除复制构造函数调用。
这种优化被称为通过返回值优化拷贝省略
此外,使用C++11的移动语义通过右值引用可能会代替拷贝语义。即使使用移动语义,编译器仍然可以自由地应用RVO。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接