我无法理解何时以及如何在C ++ 11中使用新的统一初始化语法 例如,我明白了:
std::string a{"hello world"}; // OK
std::string b{a}; // NOT OK
为什么在第二种情况下不起作用?错误是:
error: no matching function for call to ‘std::basic_string<char>::basic_string(<brace enclosed initializer list>)’
使用此版本的g ++ g++ (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2
。
对于原始数据,我应该使用什么语法?
int i = 5;
int i{5};
int i = {5};
答案 0 :(得分:20)
的编译错误
// T t{u};
std::string a;
std::string b{a};
是四件事的组合
直到不久前的草案说如果T
有一个初始化列表构造函数(std::string
有一个,取char
个元素),那么初始化列表就会自行传递作为一个论点。所以构造函数的参数不是a
,而是{a}
。
草案说初始化引用的初始化列表不是通过直接绑定完成的,而是通过首先在初始化列表中构造临时元素,然后将目标引用绑定到该临时。
草案说当初始化引用初始化列表时,当引用的初始化不是直接绑定时,转换序列是用户定义的转换序列。
草案说当在类似于上面的上下文中的重载解析场景中考虑类X
的构造函数作为候选者时传递初始化列表本身时,则在考虑类型的第一个构造函数参数时引用cv X“(cv = const / volatile) - 换句话说很可能是复制或移动构造函数,因此不允许用户定义的转换。否则,如果允许这样的转换,您可能总是在歧义中运行,因为使用列表初始化您不仅限于一个嵌套的用户定义转换。
以上所有的组合是没有构造函数可以用来取{a}
。使用initializer_list<char>
的人不匹配,而使用string&&
和const string&
的其他人则被禁止,因为他们需要用户定义的转化才能将其参数绑定到{a}
。< / p>
请注意,更新的草稿更改了第一条规则:它们表示如果没有初始化列表构造函数可以获取初始化列表,那么参数列表将包含初始化列表的所有元素。使用该更新的规则,您的示例代码将正常工作。
答案 1 :(得分:10)
第一个例子应该可以工作,调用复制构造函数。如果您正在使用GCC,则已在4.6中修复。
最后一个例子略有不同的风格差异。
int i = 5.0; // fine, stores 5
int i{5.0}; // won't compile!
int i = {5.0}; // won't compile!
不同之处在于统一初始化语法不允许缩小转换。在选择它们时,您可能需要考虑这一点。
答案 2 :(得分:4)
它不起作用,因为你忘记了分号:
std::string b{a};
^^^
否则这种语法很好,它会调用复制构造函数。
对于第二个问题,如果您想要统一,请使用int i{5};
,但int i = 5;
可能更具可读性。