Construct std::string from multiple char arrays using initializer list.

huangapple go评论65阅读模式
英文:

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{&quot;abc&quot;, &quot;bcd&quot;};
std::cout &lt;&lt; s &lt;&lt; std::endl;

Signature of constructor is string (initializer_list&lt;char&gt; il);. How does it treat (tries to treat) these char arrays exactly?

Error is as follows:

terminate called after throwing an instance of &#39;std::length_error&#39;
  what():  basic_string::_M_create
[1]    89429 IOT instruction (core dumped)  ./a.out

答案1

得分: 4

构造函数接受std::initializer_list&lt;char&gt;只能用于从多个字符创建字符串,而不能从多个其他字符串创建。例如:

std::string s{'a', 'b', 'c', 'b', 'c', 'd'};

请注意,列表初始化不仅会调用接受std::initializer_list的构造函数,还可以调用其他构造函数。只有当可以使用接受std::initializer_list的构造函数进行列表初始化时,它在重载决议中始终获胜(空列表除外,它是值初始化)。

在这种情况下,它无法使用,因此调用了另一个构造函数。
由于这个构造函数,你会得到一个错误:

template&lt; class InputIt &gt;
basic_string(InputIt first, InputIt last,
             const Allocator&amp; 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&lt;char&gt; can only be used to create a string from multiple characters, not from multiple other strings. For example:

std::string s{&#39;a&#39;, &#39;b&#39;, &#39;c&#39;, &#39;b&#39;, &#39;c&#39;, &#39;d&#39;};

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&lt; class InputIt &gt;
basic_string(InputIt first, InputIt last,
             const Allocator&amp; alloc = Allocator() );

String literals &quot;abc&quot; and &quot;bcd&quot; can be used as iterators, and if &quot;bcd&quot; &lt; &quot;abc&quot; (pointer comparison), then the computed size of the range &quot;bcd&quot; - &quot;abc&quot; 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(&quot;abc&quot;) + &quot;bcd&quot;;
// or
using namespace std::string_literals;
auto s = &quot;abc&quot;s + &quot;bcd&quot;s;

See also: std::string constructors on cppreference

huangapple
  • 本文由 发表于 2023年6月22日 20:15:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/76531791.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定