dyn*_*mic 9 c++ initialization-list c++11
考虑初始化列表构造函数用法的这个示例:
std::vector<std::string> v = { "xyzzy", "plugh", "abracadabra" };
std::vector<std::string> v({ "xyzzy", "plugh", "abracadabra" });
std::vector<std::string> v{ "xyzzy", "plugh", "abracadabra" };
Run Code Online (Sandbox Code Playgroud)
它们之间是否有任何差异(甚至是轻微的)?
在一个大型项目中,您必须定义一个标准,您会选择哪种样式?
我更喜欢第一种风格,第三种风格很容易与使用args的构造函数调用混淆.第一种风格看起来也很熟悉其他编程语言.
在的情况下vector的stringS,有三种形式之间没有什么区别.但是,如果构造函数采用initializer_listis ,则第一个和另外两个之间可能存在差异explicit.在这种情况下,第一个是复制列表初始化,不允许,而另外两个是直接列表初始化,是允许的.
由于这个原因,我的偏好将是第三种形式.我会避免第二个,因为括号是多余的.
正如Yakk在评论中指出的那样,当构造的类型没有构造函数采用时,会出现进一步的差异initializer_list.
比如说,正在构造的类型有一个构造函数,它接受3个参数,都是类型char const *,而不是initializer_list构造函数.在这种情况下,表单1和3是有效的,但是2是格式错误的,因为括在括号中时,braced-init-list与3参数构造函数不匹配.
如果类型确实具有初始化列表构造函数,但是braced-init-list的元素不能隐式转换为initializer_list<T>,则将考虑其他构造函数.假设存在另一个匹配的构造函数,表单2导致构造一个中间副本,而另外两个不构造.这可以通过以下示例来演示,编译时使用-fno-elide-constructors.
struct foo
{
foo(int, int) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
foo(foo const&) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
foo(std::initializer_list<std::string>) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
int main()
{
foo f1 = {1,2};
std::cout << "----\n";
foo f2({1,2});
std::cout << "----\n";
foo f3{1,2};
}
Run Code Online (Sandbox Code Playgroud)
输出:
foo::foo(int, int)
----
foo::foo(int, int)
foo::foo(const foo&)
----
foo::foo(int, int)
Run Code Online (Sandbox Code Playgroud)
以下案例不是问题的一部分,但仍需要注意.在某些情况下,使用嵌套大括号会导致行为不直观.考虑
std::vector<std::string> v1{{ "xyzzy", "plugh", "abracadabra" }};
std::vector<std::string> v2{{ "xyzzy", "plugh"}};
Run Code Online (Sandbox Code Playgroud)
v1按预期工作,将vector包含3个字符串,同时v2导致未定义的行为.有关详细说明,请参阅此答案.
| 归档时间: |
|
| 查看次数: |
218 次 |
| 最近记录: |