std::initializer_list std::string 的奇怪行为
Strange behavior of std::initializer_list of std::strings
这个问题很可能已经被问过了,但我没有找到答案。
下面的代码使用 gcc 编译,但在运行时使用 std::length_error(实时(崩溃。
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", "two"});
}
从字符串的初始值设定项列表创建字符串的功能似乎存在争议,例如,无法创建上面代码中注释掉的重载。
但即使允许这样的施工,为什么会导致失败?
它调用
string(const char* b, const char* e)
字符串 ctor 重载。
仅当b
和e
指向同一字符串文本时,它才有效。否则,它是未定义的行为。
对于初学者来说,没有使用接受初始值设定项列表的构造函数,因为这样的构造函数看起来像
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 一起使用,并相应地使用此大括号的 init-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';
}
相关文章:
- cppcheck在const std::string[]上引发警告
- 将std::string传递给WriteConsole API
- 为std::string的某个索引赋值
- 使用 std::string () const 函数启动线程或未来
- 当我们进行一些操作时,应该使用什么'std::string'或'std::stringstream'?
- 如何更改大小(std::string)
- std::string 的对象真的可以移动吗?
- SegFault 同时使用 std::string::operator+= 和函数作为参数
- 无法从 std::string 中提取C++ Unicode 符号
- std::string 构造函数如何处理固定大小的 char[]?
- 真的没有来自 std::string_view 的 std::string 的显式构造函数吗?
- 将C++ std::string 转换为 UTF-16-LE 编码的字符串
- 重载 + 自己的类和 std::string 的运算符
- 如何使用 std::string 作为 QHash 的键?
- 将日语 wstring 转换为 std::string
- 可以从std::string继承以提供类型一致性吗
- 构造函数采用std::string_view与std::string并移动
- 在共享缓冲区内存中创建 ::std::string 对象
- std::string.size() 未知行为
- Valgrind 在 std::string::swap 中报告 SIGILL