作者:树缝中间_324 | 来源:互联网 | 2023-09-25 11:15
IhaveaclasswithanarraymemberthatIwouldliketoinitializetoallzeros.我有一个数组成员的类,我想初始化为全
I have a class with an array member that I would like to initialize to all zeros.
我有一个数组成员的类,我想初始化为全零。
class X
{
private:
int m_array[10];
};
For a local variable, there is a straightforward way to zero-initialize (see here):
对于局部变量,有一种简单的零初始化方法(参见此处):
int myArray[10] = {};
Also, the class member m_array
clearly needs to be initialized, as default-initializing ints will just leave random garbage, as explained here.
此外,类成员m_array显然需要初始化,因为默认初始化的int将只留下随机垃圾,如此处所述。
However, I can see two ways of doing this for a member array:
但是,我可以看到两种方法为成员数组执行此操作:
With parentheses:
public:
X()
: m_array()
{}
With braces:
public:
X()
: m_array{}
{}
Are both correct? Is there any difference between the two in C++11?
两个都正确吗?这两者在C ++ 11中有什么区别吗?
3 个解决方案
12
Initialising any member with ()
performs value initialisation.
使用()初始化任何成员执行值初始化。
Initialising any class type with a default constructor with {}
performs value initialisation.
使用带有{}的默认构造函数初始化任何类类型都会执行值初始化。
Initialising any other aggregate type (including arrays) with {}
performs list initialisation, and is equivalent to initialising each of the aggregate's members with {}
.
使用{}初始化任何其他聚合类型(包括数组)执行列表初始化,相当于使用{}初始化每个聚合的成员。
Initialising any reference type with {}
constructs a temporary object, which is initialised from {}
, and binds the reference to that temporary.
使用{}初始化任何引用类型构造一个临时对象,该对象从{}初始化,并将引用绑定到该临时对象。
Initialising any other type with {}
performs value initialisation.
使用{}初始化任何其他类型执行值初始化。
Therefore, for pretty much all types, initialisation from {}
will give the same result as value initialisation. You cannot have arrays of references, so those cannot be an exception. You might be able to construct arrays of aggregate class types without a default constructor, but compilers are not in agreement on the exact rules. But to get back to your question, all these corner cases do not really matter for you: for your specific array element type, they have the exact same effect.
因此,对于几乎所有类型,从{}初始化将产生与值初始化相同的结果。您不能拥有引用数组,因此这些不能成为例外。您可以在没有默认构造函数的情况下构造聚合类类型的数组,但编译器对确切的规则不一致。但是回到你的问题,所有这些极端情况对你来说并不重要:对于你特定的数组元素类型,它们具有完全相同的效果。
11
The types of initialization can be kind of tedious to go through, but in this case it is trivial. For:
初始化的类型可能有点繁琐,但在这种情况下,它是微不足道的。对于:
public:
X()
: m_array()
{}
since the expression-list between the parentheses are empty, value-initialization occurs. Similarly for:
由于括号之间的表达式列表为空,因此会进行值初始化。同样适用于:
public:
X()
: m_array{}
{}
list-initialization occurs, and subsequently value-initialization since the brace-init-list is empty.
由于brace-init-list为空,因此会发生list-initialization,然后进行值初始化。
To give a more comprehensive answer, let's go through §8.5 of N4140.
为了给出更全面的答案,让我们来看看N4140的§8.5。
- If no initializer is specified for an object, the object is default-initialized. When storage for an object with automatic or dynamic storage duration is obtained, the object has an indeterminate value, and if no initialization is performed for the object, that object retains an indeterminate value until that value is replaced (5.17).
如果没有为对象指定初始化程序,则默认初始化该对象。当获得具有自动或动态存储持续时间的对象的存储时,该对象具有不确定的值,并且如果没有对该对象执行初始化,则该对象保留不确定的值,直到该值被替换(5.17)。
This indeterminate value is what you refer to as garbage values.
这个不确定的值就是你所说的垃圾值。
To zero-initialize an object or reference of type T
means:
零初始化T类型的对象或引用意味着:
— if T is an array type, each element is zero-initialized
- 如果T是数组类型,则每个元素都是零初始化的
To value-initialize an object of type T
means:
对T类型的对象进行值初始化意味着:
— if T is a (possibly cv-qualified) class type ... then the object is default-initialized; ...
- 如果T是(可能是cv限定的)类类型...那么该对象是默认初始化的; ...
— if T is an array type, then each element is value-initialized;
- 如果T是数组类型,则每个元素都是值初始化的;
— otherwise, the object is zero-initialized.
- 否则,对象被零初始化。
The semantics of initializers are as follows. ... — If the initializer is a (non-parenthesized) braced-init-list, the object or reference is list-initialized (8.5.4).
初始化器的语义如下。 ... - 如果初始化程序是(非括号的)braced-init-list,则对象或引用是列表初始化的(8.5.4)。
— If the initializer is (), the object is value-initialized.
- 如果初始值设定项为(),则对象进行值初始化。
So far it's clear that value initialization will make each element of the array zero since int
is not a class type. But we have not yet covered list initialization and aggregate initialization, since an array is an aggregate.
到目前为止,很明显值初始化将使数组的每个元素为零,因为int不是类类型。但是我们还没有介绍列表初始化和聚合初始化,因为数组是一个聚合。
§8.5.4:
List-initialization of an object or reference of type T
is defined as follows:
列表初始化对象或类型T的引用定义如下:
— If T is an aggregate, aggregate initialization is performed (8.5.1).
- 如果T是聚合,则执行聚合初始化(8.5.1)。
And back to §8.5.1:
并回到§8.5.1:
- If there are fewer initializer-clauses in the list than there are members in the aggregate, then each member not explicitly initialized shall be initialized from its brace-or-equal-initializer or, if there is no brace-or-equal-initializer, from an empty initializer list (8.5.4).
如果列表中的initializer-clause少于聚合中的成员,那么未明确初始化的每个成员都应从其brace-or-equal-initializer初始化,或者如果没有bra-or-equal-initializer,从一个空的初始化列表(8.5.4)。
And we end with §8.5.4 again:
我们再次以§8.5.4结尾:
List-initialization of an object or reference of type T
is defined as follows:
列表初始化对象或类型T的引用定义如下:
— Otherwise, if the initializer list has no elements, the object is value-initialized.
- 否则,如果初始化列表没有元素,则对象进行值初始化。
Since traversing the (draft) standard can take breath out of you, I recommend cppreference as it breaks it down pretty good.
由于遍历(草案)标准可能会让你失望,我建议使用cppreference,因为它可以很好地分解它。
Relevant links:
cppreference:
aggregate initialization
value initialization
Draft standard: