4

不太明白为什么当我使用 VC2010 以调试模式构建时不调用此复制构造函数。

class SomeClass
{
public:
    SomeClass(int meaningless){}

    SomeClass(const SomeClass& sc)
    {
        cout << "Copy Constructor invoked!" << endl;
    }
};

int main()
{
    SomeClass test(SomeClass(9999));  // Copy constructor not invoked. 
}

我认为这与 RVO 无关,因为我没有返回任何值。

更有趣的是,当我将复制构造函数设为私有时,即使省略了复制构造函数,编译器也不会编译。

4

2 回答 2

5

它是由编译器完成的优化。根据语言规范,允许编译器尽可能省略对复制构造函数的调用。

一个可访问的复制构造器仅用于语义检查,即使它实际上并没有被调用。语义检查是在优化之前完成的。

但是,如果您-fno-elide-constructors使用 GCC 选项编译它,则不会执行复制省略,而是会调用复制构造函数。GCC 文档说,

-fno-elide-constructors

C++ 标准允许实现省略创建仅用于初始化相同类型的另一个对象的临时对象。指定此选项会禁用该优化,并强制 G++ 在所有情况下调用复制构造函数。

使用 MSVC10,您可以使用/Od,根据 MSDN,它会关闭程序中的所有优化。

注意:维基百科有一篇关于复制省略的文章

于 2012-04-18T01:00:34.527 回答
4

根据 C++11 标准,§12.8.31:

…This elision of copy/move operations, called copy elision, is permitted in the following circumstances (which may be combined to eliminate multiple copies):

…</p>

  • when a temporary class object that has not been bound to a reference would be copied/moved to a class object with the same cv-unqualified type, the copy/move operation can be omitted by constructing the temporary object directly into the target of the omitted copy/move

Temporary objects get a lot of leeway in C++, and compilers will be pretty aggressive when removing them. If your object had a lifetime of its own in any way, then the copy constructor would end up being called.

However, I would definitely expect it to check the copy constructor's access modifier, though I can see an argument that you shouldn't (after all, you just aren't calling the copy constructor). But that probably wouldn't be very good practice, since copy elision is optional.

于 2012-04-18T01:05:24.993 回答