哪些贪婪的初始化列表示例潜伏在标准库中?

Tem*_*Rex 13 c++ initializer-list c++11 list-initialization

从C++ 11开始,标准库容器和std::string构造函数都采用初始化列表.这个构造函数优先于其他构造函数(甚至,正如@ JohannesSchaub-litb在评论中指出的那样,甚至忽略了其他"最佳匹配"标准).当将所有带括号()的构造函数转换为其支撑版本时,这会导致一些众所周知的陷阱{}

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
#include <string>

void print(std::vector<int> const& v)
{
    std::copy(begin(v), end(v), std::ostream_iterator<int>(std::cout, ","));
    std::cout << "\n";
}

void print(std::string const& s)
{
    std::cout << s << "\n";
}

int main()
{
    // well-known 
    print(std::vector<int>{ 11, 22 });  // 11, 22, not 11 copies of 22
    print(std::vector<int>{ 11 });      // 11,     not 11 copies of 0

    // more surprising
    print(std::string{ 65, 'C' });      // AC,     not 65 copies of 'C'
}
Run Code Online (Sandbox Code Playgroud)

我在这个网站上找不到第三个例子,这个问题出现在Lounge <C++>聊天中(与@rightfold讨论,@ Abyx和@JerryCoffin),有点令人惊讶的是转换std::string构造函数需要计算并且要使用的字符{}代替(),将其含义从n字符副本更改为n第-62个字符(通常来自ASCII表),后跟另一个字符.

这通常不会限制缩小转换,因为65是一个常量表达式,可以表示为char,并在转换回int时保留其原始值(§8.5.4/ 7,bullet 4)(谢谢到@JerryCoffin).

问题:标准库中是否有更多示例将()样式构造函数转换为{}样式,初始化列表构造函数是否贪婪地匹配?

Die*_*ühl 5

我假设,在您的示例中std::vector<int>std::string您还打算涵盖其他容器,例如std::list<int>std::deque<int>、 等,它们显然具有相同的问题,如std::vector<int>. 同样,int不是唯一的类型,它也适用于charshortlong和他们的unsigned版本(可能是一些其他的整数类型,太)。

我认为也有,std::valarray<T>但我不确定是否T允许为整型。实际上,我认为这些具有不同的语义:

std::valarray<double>(0.0, 3);
std::valarray<double>{0.0, 3};
Run Code Online (Sandbox Code Playgroud)

还有一些其他标准 C++ 类模板将 astd::initializer_list<T>作为参数,但我认为其中任何一个都没有重载构造函数,可以在使用括号而不是大括号时使用。

  • 哦,太棒了,`std::valarray` 有 `(val, count)` 而不是像所有序列容器那样的 `(count, val)`,更容易出错 (2认同)
  • @TemplateRex:据我所知,当您在源代码中键入 `std::valarray` 时,您犯了一个错误。 (2认同)