空括号调用默认构造函数还是调用std :: initializer_list的构造函数? [英] Do empty braces call the default constructor or the constructor taking an std::initializer_list?

查看:247
本文介绍了空括号调用默认构造函数还是调用std :: initializer_list的构造函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是有效现代C ++ (第55页)的报价:

The following is a quote from Effective Modern C++ (page 55):


使用一个空的大括号来构造一个支持默认构造函数的对象,并且支持std :: initializer_list构造,你的空大括号是什么意思等等。规则是你得到默认构造。

"Suppose that you use an empty set of braces to construct an object that supports default constructor and also supports std::initializer_list construction. What do your empty braces mean? etc. The rule is that you get default construction."

我尝试过使用std :: array:

I tried this with std::array:

std::array<int, 10> arr{};

,并收到g ++(版本4.8.2)的警告:

and got the warning from g++ (version 4.8.2):


警告:成员'std :: array< int,10ul> :: _ M_elems'

warning: missing initializer for member ‘std::array<int, 10ul>::_M_elems’

这是当试图从一个空的 std :: initializer_list 构造 std :: array code>(请参阅为什么我可以从{}初始化一个规则数组,但不是一个std ::数组的讨论这个警告)。

which is the warning one gets when trying to construct an std::array from an empty std::initializer_list (see Why can I initialize a regular array from {}, but not a std::array for a discussion of this warning).

那么,为什么上面的代码不能解释为调用默认构造函数呢?

So, why isn't the above line of code interpreted as calling the default constructor?

推荐答案

这是因为 std :: array 是一个汇总,因此汇总初始化,这在 draft C ++ 11 standard section 8.5.4 [dcl.init.list] 其中说:

That is because std::array is an aggregate and therefore aggregate initialization is performed this is covered in the draft C++11 standard section 8.5.4 [dcl.init.list] which says:


类型T的对象或引用的列表初始化定义如下:

List-initialization of an object or reference of type T is defined as follows:


  • 如果初始化器列表没有元素,T是带有默认构造函数的类类型,则对象为
    值初始化。

  • If the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.

否则,如果T是聚合,则执行聚合初始化(8.5.1)。

Otherwise, if T is an aggregate, aggregate initialization is performed (8.5.1).

double ad[] = { 1, 2.0 }; // OK
int ai[] = { 1, 2.0 }; // error: narrowing

struct S2 {
  int m1;
  double m2, m3;
};

S2 s21 = { 1, 2, 3.0 }; // OK
S2 s22 { 1.0, 2, 3 }; // error: narrowing
S2 s23 { }; // OK: default to 0,0,0


我们可以看到它是不是一个聚合,然后列表继续说:

and we can see if it is not an aggregate then the list goes on and says:



  • 否则,如果T是std :: initializer_list的特殊化,则initializer_list对象是
    ,如下所述被构造,并且用于根据初始化的规则初始化对象

  • 否则,如果T是类类型,则考虑构造函数。适用的构造函数枚举为
    ,最好的构造函数通过重载分辨率(13.3,13.3.1.7)选择。如果转换任何参数需要缩小转换(参见下面的
    ),程序就会形成错误。

我们可以确认 std :: array 部分的集合23.3.2.1 [array.overview]


数组是一个聚合
语法

An array is an aggregate (8.5.1) that can be initialized with the syntax

array<T, N> a = { initializer-list };

其中initializer-list是最多N个元素的逗号分隔列表
类型可转换为T。

where initializer-list is a comma-separated list of up to N elements whose types are convertible to T.

8.5.1 引用 8.5.1 汇总 [dcl.init.aggr] 并说:


当初始化器列表初始化聚合时,如8.5.4中指定的
,初始化器列表的元素被作为聚合成员的
初始化器,增加下标
或会员订单[...]

When an aggregate is initialized by an initializer list, as specified in 8.5.4, the elements of the initializer list are taken as initializers for the members of the aggregate, in increasing subscript or member order [...]

,我们回到 4 这是我们开始的地方。

and we come full-circle back to section 8.5.4 which is where we started.

这篇关于空括号调用默认构造函数还是调用std :: initializer_list的构造函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆