对于初学者来说,没有使用接受初始化列表的构造函数,因为这样的构造函数看起来像
basic_string(initializer_list<charT>, const Allocator& = Allocator());
^^^^^
所以编译器搜索另一个合适的构造函数,它找到了这样的构造函数。它是构造函数
template<class InputIterator>
basic_string(InputIterator begin, InputIterator end, const Allocator& a = Allocator());
那是表达式"one","two"被认为是类型的迭代器const char *。
因此该函数test具有未定义的行为。
例如,您可以编写(假设具有相同内容的字符串文字作为一个字符串文字存储在内存中,这不能保证并且取决于所选的编译器选项)。
#include <iostream>
#include <string>
void test(const std::string &value) { std::cout << "string overload: " << value << std::endl; }
//void test(const std::vector<std::string> &) { std::cout << "vector overload" << std::endl; }
int main()
{
test({ "one", "one" + 3 });
}
你会得到一个有效的结果。
string overload: one
注意这个结构
{ "one", "two" }
不是类型的对象std::initializer_list<T>。这种结构没有类型。它是braced-init-list用作初始化器的。只需编译器首先尝试使用具有 std::initializer_list 类型的第一个参数的构造函数来与此初始化器一起使用。
例如,如果您将使用该类std::vector<const char *>,那么编译器确实会将其构造函数与 std::initializer_list 一起使用,并相应地使用此花括号初始化列表初始化其参数。例如
#include <iostream>
#include <vector>
int main()
{
std::vector<const char *> v( { "one", "two" } );
for ( const auto &s : v ) std::cout << s << ' ';
std::cout << '\n';
}