我正在玩一些无用的代码来理解成员引用的初始化,并碰到了这个:
struct A {};
struct B
{
B() : a()
{
}
const A& a;
};
Run Code Online (Sandbox Code Playgroud)
使用gcc 4.9.2编译时,上面的代码给出以下错误:
In constructor 'B::B()':
error: value-initialization of reference type 'const A&'
B() : a()
Run Code Online (Sandbox Code Playgroud)
我明白了
但是如果我在B的构造函数的初始化列表中使用统一初始化,就像这样:
struct A {};
struct B
{
B() : a{}
{
}
const A& a;
};
Run Code Online (Sandbox Code Playgroud)
它汇编很好.
所以问题是,为什么在这里使用统一初始化会改变编译结果?
我也尝试使用Microsoft Visual C++ 2013.它不编译任何版本的代码,并使用相同的错误消息:
Error 3 error C2440: 'initializing' : cannot convert from 'int' to 'const A &
Run Code Online (Sandbox Code Playgroud)
你可以在这里快速玩它:
给定以下结构:
struct ABC
{
ABC(){cout << "ABC" << endl;}
~ABC() noexcept {cout << "~ABC" << endl;}
ABC(ABC const&) {cout << "copy" << endl;}
ABC(ABC&&) noexcept {cout << "move" << endl;}
ABC& operator=(ABC const&){cout << "copy=" << endl;}
ABC& operator=(ABC&&) noexcept {cout << "move=" << endl;}
};
Run Code Online (Sandbox Code Playgroud)
输出:
std::pair<std::string, ABC> myPair{{}, {}};
Run Code Online (Sandbox Code Playgroud)
是:
ABC
copy
~ABC
~ABC
Run Code Online (Sandbox Code Playgroud)
而输出:
std::pair<std::string, ABC> myPair{{}, ABC{}};
Run Code Online (Sandbox Code Playgroud)
是:
ABC
move
~ABC
~ABC
Run Code Online (Sandbox Code Playgroud)
在试图理解两者之间的差异时,我认为我已经确定第一种情况是使用复制列表初始化,而第二种情况使用未命名临时的直接列表初始化(数字7和2分别在这里) :http://en.cppreference.com/w/cpp/language/list_initialization).
搜索类似的问题我发现:为什么标准区分直接列表初始化和复制列表初始化?并且:复制列表初始化是否从概念上调用了复制ctor?.
这些问题的答案讨论了这样一个事实:对于复制列表初始化,使用显式构造函数会使代码格式错误.事实上,如果我将ABC的默认构造函数显式化,我的第一个例子将不会编译,但这可能是(可能)另一个问题.
所以,问题是:为什么临时复制在第一种情况下,但在第二种情况下移动?什么阻止它在复制列表初始化的情况下被移动?
作为注释,以下代码: …