使用双大括号初始化字符串向量

9
有人能解释一下下面示例中使用双括号和单括号初始化的行为差异吗? 代码 #1:
vector<string> v = {"a", "b"};
string c(v[0] + v[1]);
cout << "c = " << c;
cout << "c.c_str() = " << c.c_str();

输出 #1:

c = ab
c.c_str() = ab

代码 #2:


vector<string> v = {{"a", "b"}};
string c(v[0] + v[1]);
cout << "c = " << c;
cout << "c.c_str() = " << c.c_str();

输出 #2:

c = a\acke�Z\ 
c.c_str() = a

我测试了Code#2,并在以下行抛出异常:vector<string> v = {{"a", "b"}}; - Farhad
1个回答

16

隐式转换是核心。这就是发生的事情。

  1. vector<string> v = {"a", "b"}; 通过提供一个有两个元素的初始化列表来初始化向量。这两个std::string从字符串字面值初始化,然后复制到向量中。

  2. vector<string> v = {{"a", "b"}}; 通过提供一个有两个元素的初始化器来初始化向量,其中单个std::string被初始化。访问向量的第二个元素具有未定义的行为。

现在,这里有趣的部分。在访问 v[1] 之前,第二段代码已经存在未定义的行为。重载分辨率(用于构造单个的 std::string)选择构造函数。最佳可行构造函数是这样的:

template< class InputIt >
basic_string( InputIt first, InputIt last, 
              const Allocator& alloc = Allocator() );

由于将 InputIt 推断为 char const [2](并进行函数参数调整,将其转换为 char const*),因此它们实际上不是迭代器,所有事情都变得一团糟。


1
请参见 https://dev59.com/9KXja4cB1Zd3GeqPXNXM,也许您可以解释一下两者之间的区别。 - bolov
第二个示例不应该编译通过吗?为什么编译器会看到{"a", "b"}并说:“是的,那是一个字符串…”? - PeterT
@PeterT - 它没有说那个。它说的是“我能把它变成一个字符串吗”。可悲的是,它确实可以。 - StoryTeller - Unslander Monica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接