为什么初始化列表与表达式列表相比具有不同的结果

时间:2018-06-08 16:24:30

标签: c++ constructor initializer-list

当我在下面编写一些代码时,我感到很奇怪。我期待相同的输出,但结果证明是错误的。为什么2个语句具有不同的输出,(expression-list)和{initializer-list}之间有什么区别?

cout << string(4, 'c') << endl;  
cout << string{ 4, 'c' } << endl; 

输出是:

cccc  
c   //a square '' before 'c'

2 个答案:

答案 0 :(得分:5)

来自cppreference.com

  

否则,T的构造函数分为两个阶段:

     
      
  • 检查以std::initializer_list为唯一参数的所有构造函数,或者如果其余参数具有默认值,则作为第一个参数,并针对类型为{{1的单个参数的重载决策进行匹配}}

  •   
  • 如果前一阶段没有产生匹配,则std::initializer_list的所有构造函数都参与对由 braced-init-list 元素组成的参数集进行重载解析。 em>,限制条件是只允许非缩小转换。如果此阶段产生显式构造函数作为复制列表初始化的最佳匹配,则编译失败(注意,在简单的复制初始化中,不考虑显式构造函数全部)。

  •   

在你的情况下

T

使用以下构造函数。

string(4, 'c')

另一方面,

std::string(size_type count, 
            char ch, 
            const Allocator& alloc = Allocator() );

使用以下构造函数。

string{ 4, 'c' }

如果没有在std::string(std::initializer_list<char> ilist, const Allocator& alloc = Allocator() ); 中定义第二个构造函数,那么这两个构造函数都会产生相同的对象。

答案 1 :(得分:4)

两者都是constructor次调用,但它们调用两个不同的构造函数。第一个电话(&#34; 2&#34;在链接中)构建了一个字符计数,因此你得到了4&#39; c。

第二个构造函数(&#34; 9&#34;在链接中)采用std::initializer_list。使用大括号而不是parens构造时,如果该类有一个构造函数采用initializer_list,它将始终优先。

如果有任何安慰,这种行为多年来困扰了程序员很多 ...