2016-12-06 56 views
1

我很好奇C++ 11列表初始化。我定义了一个类:为什么在这种情况下复制构造函数匹配?

class base{ 
    base() { cout << "default ctor" << endl;} 
    base(std::initiazer_list<base> il) { cout << "list initialization << endl;} 
    base(const base &rhs) { cout << "copy ctor" << endl;} 
} 

在主函数中,我初始化两个对象来测试我的类。

int main() 
{ 
    base obj{}; // default ctor 
    base obj2{obj}; // copy ctor 
} 

我从“有效的现代C++”调用使用列表的初始化语法强烈希望重载采取std::initializer_list学习。 因此,就我而言,我认为第二个ctor会被调用,但是第三个调用会被调用。

你能解释一下为什么吗?

+0

首先,这不是真正的代码。其次,你的编译器/版本是什么?这方面的规则经历了一些近期的变化。 –

+0

我知道我的代码没有一些实际意义。我在Visual Studio 2017RC中测试我的代码。 – linyuwang

+0

我不在乎“实际意义”。这显然不是你测试的代码。 –

回答

0

Demo

default ctor 
copy ctor 
list initialization 

因此,它是在第一个拷贝构造函数被调用拷贝到obj然后std::initializer_list<base>适当的构造函数重载(这是一个用于初始化列表)被称为感正确的。

base obj2{obj}; // copy ctor 

正如你所看到的,这包括两个调用,而不是一个。一个要复制,一个要列出初始化。列表初始化器是强烈首选的重载。该副本将初始化该超载的参数。

编辑:gcc和clang因版本而异。

GCC Head Clang Head

我认为发生的事情是,libstdc++实施std::initializer_list创建临时对象,而铛拿起拷贝构造函数,而不是初始化列表超载。

编辑2: 我检查了这个在我的本地系统上,铛-stdlib=libstdc++确实创建了临时的std::initializer_list,因此调用复制构造函数存在。

所有编译器都正确

+0

感谢您的回答。在我的IDE(Visual Studio 2017RC)中,我的代码输出与你的代码不一样。那么,你的意思是它取决于编译器? – linyuwang

+0

@linyuwang请检查编辑。它依赖于标准的库实现和编译器。 – themagicalyang

+0

Clang处于一种奇怪的状态:它实现了CWG1467(其中包括 - 这表示这是复制构造函数),但不是CWG2137(它将CWG1467的这部分恢复为非聚合)。 –

相关问题