英文:
Construct std::string from multiple char arrays using initializer list
问题
构建一个std::string
实例时,通过提供一个包含多个C风格字符串的初始化列表不会导致编译错误,但会导致运行时错误。代码如下:
std::string s{"abc", "bcd"};
std::cout << s << std::endl;
构造函数的签名是string (initializer_list<char> il);
。它会如何(试图)处理这些字符数组?
错误信息如下:
terminate called after throwing an instance of 'std::length_error'
what(): basic_string::_M_create
[1] 89429 IOT instruction (core dumped) ./a.out
英文:
Just a reminder, I am not asking for a solution to solving this problem, but rather an explanation of a behaviour. Constructing an instance of std::string
by providing an initializer-list with multiple C style strings does not result in a compilation error, but does in a runtime error. Code is as follows:
std::string s{"abc", "bcd"};
std::cout << s << std::endl;
Signature of constructor is string (initializer_list<char> il);
. How does it treat (tries to treat) these char arrays exactly?
Error is as follows:
terminate called after throwing an instance of 'std::length_error'
what(): basic_string::_M_create
[1] 89429 IOT instruction (core dumped) ./a.out
答案1
得分: 4
构造函数接受std::initializer_list<char>
只能用于从多个字符创建字符串,而不能从多个其他字符串创建。例如:
std::string s{'a', 'b', 'c', 'b', 'c', 'd'};
请注意,列表初始化不仅会调用接受std::initializer_list
的构造函数,还可以调用其他构造函数。只有当可以使用接受std::initializer_list
的构造函数进行列表初始化时,它在重载决议中始终获胜(空列表除外,它是值初始化)。
在这种情况下,它无法使用,因此调用了另一个构造函数。
由于这个构造函数,你会得到一个错误:
template< class InputIt >
basic_string(InputIt first, InputIt last,
const Allocator& alloc = Allocator() );
字符串字面值"abc"
和"bcd"
可以用作迭代器,如果"bcd" < "abc"
(指针比较),则计算出的范围大小为"bcd" - "abc"
为负数,或者在转换为std::size_t
后为五万亿字节,这可能对您的系统来说略微过大。结果会引发std::length_error
。
解决方法
要从一个或多个字符串构造字符串,您可以这样做:
auto s = std::string("abc") + "bcd";
// 或者
using namespace std::string_literals;
auto s = "abc"s + "bcd"s;
另请参阅:std::string
构造函数cppreference
英文:
The constructor which takes an std::initializer_list<char>
can only be used to create a string from multiple characters, not from multiple other strings. For example:
std::string s{'a', 'b', 'c', 'b', 'c', 'd'};
Note that list initialization will not only call constructors that accept std::initializer_list
, it can also call other constructors.
Only if a constructor taking std::initializer_list
can be called with list initialization, it always wins in overload resolution (with the exception of an empty list, which is value initialization).
In this case, it can't be used, so another constructor is called.
You're getting an error because of this constructor:
template< class InputIt >
basic_string(InputIt first, InputIt last,
const Allocator& alloc = Allocator() );
String literals "abc"
and "bcd"
can be used as iterators, and if "bcd" < "abc"
(pointer comparison), then the computed size of the range "bcd" - "abc"
is negative, or in the quintillions of bytes after conversion to std::size_t
, which might be slightly too large for your system. As a result, std::length_error
is thrown.
Solution
To construct a string from one or multiple strings, you could do:
auto s = std::string("abc") + "bcd";
// or
using namespace std::string_literals;
auto s = "abc"s + "bcd"s;
See also: std::string
constructors on cppreference
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论