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

标签 c++ c++11 initializer-list 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'
}

我在这个网站上找不到第三个例子,这件事出现在 Lounge 聊天中(正在与 @rightfold、@Abyx 和 @JerryCoffin 讨论),有点令人惊讶的是,将 std::string 构造函数采用计数和字符来使用 {} 而不是 (),将其含义从 n 将字符复制到第 n 个字符(通常来自 ASCII 表),后跟另一个字符。

这并没有被缩小转换的通常大括号禁止所捕获,因为 65 是一个可以表示为 char 的常量表达式,并且在转换回 int 时将保留其原始值(第 8.5.4/7 节,项目符号 4 )(感谢@JerryCoffin)。

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

最佳答案

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

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

std::valarray<double>(0.0, 3);
std::valarray<double>{0.0, 3};

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

关于c++ - 哪些贪婪的初始化列表示例潜伏在标准库中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19847960/

相关文章:

c++ - 为什么我的打印功能不起作用?链表

c++ - 这种元组的递归引用安全吗?

c++ - 如何避免 "template parameters not deducible in partial specialization"

c++ - 无法从初始化列表中的 lambda 中推断出类型

c++ - std::vector 大小?

c++ - 我的 For 循环出现段错误

c++ - 等待其他线程继续

c++ - 在新的 C++11 中可以创建可选引用吗?

linux - GCC版本是4.8,在centos中仍然出现unrecognized command -std=c++11的错误

c++ - 为什么我的模板不接受初始化列表