3

我对这个关于初始化的语法有疑问。

引自http://en.wikipedia.org/wiki/Copy_constructor

X a = X();
// valid given X(const X& copy_from_me) but not valid given X(X& copy_from_me)               
// because the second wants a non-const X&               
// to create a, the compiler first creates a temporary by invoking the default constructor               
// of X, then uses the copy constructor to initialize a as a copy of that temporary.                
// However, for some compilers both the first and the second actually work.

#include <iostream>

class Foo
{
public:
    Foo()
    {
        std::cout << "Default Constructor called" << std::endl;
    }

    Foo(const Foo& other)
    {
        std::cout << "Copy constructor called" << std::endl;
    }

    Foo& operator=(const Foo& rhs)
    {
        std::cout << "Assignment operator called" << std::endl;
    }
};

int main()
{
    Foo b = Foo(); //case 1:default 
    Foo c = Foo(a); //case 2: copy constructor
}

案例 1:
在复制构造函数中将参数从 const 更改为非 const 时,案例 1 不会按维基百科的预期编译。但是,当使用正确的复制构造函数运行时,它只调用默认构造函数。为什么它也不调用复制构造函数?这是在编译时完成的优化吗?

案例 2:
案例 1 的答案可能会为我回答案例 2,但是为什么这只会调用一次复制构造函数呢?

4

2 回答 2

4
Foo b = Foo();

这种形式需要一个有效的匹配副本构造函数存在,但副本可能会被优化掉。它可以被优化掉的事实并没有放松构造函数存在的要求。

通过使您的复制构造函数采用非常量引用,它不再匹配,因为Foo()会生成一个临时对象,并且临时对象不能绑定到非常量引用。当您制作参数 const 引用(或废弃您的副本 c-tor 并使用编译器生成的副本 c-tor)时,它会起作用,因为临时对象可以绑定到 const 引用。

于 2012-05-24T19:45:44.047 回答
1

X()是一个临时的,所以你不能将它绑定到一个非const引用(尽管 MSVS 有一个允许它的扩展)。

1)是的,这是一个编译器优化

2) 非法,因为a不存在。但原则上,再次,是的,编译器优化。

于 2012-05-24T19:46:36.777 回答