14

我无法理解何时以及如何在 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};
4

3 回答 3

20

的编译错误

// T t{u};
std::string a;
std::string b{a};

是四样东西的组合

  • 直到不久前的草案说如果T有一个初始化列表构造函数(std::string有一个,带char元素),初始化列表本身作为参数传递。所以构造函数的参数不是a,而是{a}

  • 草案说,初始化引用的初始化列表不是通过直接绑定来完成的,而是首先从初始化列表中的元素构造一个临时对象,然后将目标引用绑定到该临时对象。

  • 草案说,当通过初始化列表初始化引用时,当引用的初始化不是直接绑定时,转换序列是用户定义的转换序列。

  • 草案说,当X在上述上下文中考虑类的构造函数作为重载解决方案中的候选者时,传递初始化器列表本身时,然后在考虑类型为“对 cv X 的引用”(cv = const / volatile)的第一个构造函数参数时) - 换句话说,很可能是复制或移动构造函数,则不允许用户定义的转换。否则,如果允许这样的转换,您总是会在模棱两可的情况下运行,因为使用列表初始化,您不仅限于一个嵌套的用户定义转换。

以上所有的组合是没有构造函数可以用来获取{a}. 一个 usinginitializer_list<char>不匹配,而其他使用string&&andconst string&被禁止,因为它们需要用户定义的转换才能将其参数绑定到{a}.

请注意,最近的草案更改了第一条规则:他们说如果没有初始化列表构造函数可以获取初始化列表,则参数列表由初始化列表的所有元素组成。使用更新后的规则,您的示例代码可以正常工作。

于 2011-09-30T16:40:04.293 回答
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!

不同之处在于统一初始化语法不允许缩小转换。在它们之间进行选择时,您可能需要考虑到这一点。

于 2011-09-30T16:15:56.510 回答
4

它不起作用,因为您忘记了分号:

std::string b{a};
               ^^^

否则这个语法很好,它会调用复制构造函数。

对于第二个问题,int i{5};如果您想统一,请使用,但int i = 5;可能更具可读性。

于 2011-09-30T14:48:20.017 回答