简体   繁体   English

使用复制列表初始化程序进行 C++ 对象初始化

[英]C++ object initialization with copy-list-initializer

// Example program
#include <iostream>
#include <string>

class T{
public:   
    int x, y;
    T(){
        std::cout << "T() constr called..." << std::endl;
    };
    T(int x, int y):x(x),y(y){
        std::cout << "T(x,y) constr called..." << std::endl;
    }
    
    void inspect(){
        std::cout << "T.x: " << this->x << std::endl;
        std::cout << "T.y: " << this->y << std::endl;
    }
};

int main()
{
    T t1(5,6);
    t1.inspect();
    
    std::cout << std::endl;
    
    T t2 = {};
    t2.inspect();
}

I am getting the following result:我得到以下结果:

T(x,y) constr called...
T.x: 5
T.y: 6

T() constr called...
T.x: 208787120
T.y: 31385

The members of t2 instance were not zero initialized (what I wanted to achieve). t2实例的成员不是零初始化(我想要实现的)。 Do I understand it correctly, that if I have a constructor defined, it will not perform a zero initialization?我是否正确理解,如果我定义了一个构造函数,它不会执行零初始化? (I know how to achieve initialization to zero using explicit default values. The problem is why I am not able to do it using the init-list) (我知道如何使用显式默认值实现初始化为零。问题是为什么我不能使用 init-list 来做到这一点)

List initialization列表初始化

Otherwise, if the braced-init-list is empty and T is a class type with a default constructor, value-initialization is performed.否则,如果花括号初始化列表为空并且 T 是具有默认构造函数的类类型,则执行值初始化。

Value-initialization值初始化

In all cases, if the empty pair of braces {} is used and T is an aggregate type, aggregate-initialization is performed instead of value-initialization.在所有情况下,如果使用空大括号 {} 并且 T 是聚合类型,则执行聚合初始化而不是值初始化。

Aggregate-initialization (it seems this is not my case and therefore it is not initializing members to zero)聚合初始化(这似乎不是我的情况,因此它不会将成员初始化为零)

An aggregate is one of the following types:聚合是以下类型之一:

  • class type (typically, struct or union), that has类类型(通常为结构体或联合体),具有
    • no user-declared constructors没有用户声明的构造函数

What would be the simplest and less error-prone modification of legacy code, where I need to solve issues where some class members are used before they are initialized?对遗留代码最简单且不易出错的修改是什么,我需要解决在初始化之前使用某些类成员的问题?

The data members of t2 have garbage value . t2的数据成员具有垃圾值 This is because they are of built-in type and you did not intialized them explicitly.这是因为它们是内置类型并且您没有显式初始化它们。 The solution would be to:解决办法是:

Solution 1 : Use constructor initializer list解决方案 1 :使用构造函数初始值设定项列表

T(): x(0), y(0){
        std::cout << "T() constr called..." << std::endl;
    };

Solution 2 : Use in-class initializer解决方案 2 :使用类内初始化程序

int x = 0, y = 0;

This is why it is advised that:这就是为什么建议

always initialize built-in type in block/local scope始终在块/局部范围内初始化内置类型

If you use any of the above given solution, the output will be:如果您使用上述任何一种解决方案,输出将是:

T(x,y) constr called...
T.x: 5
T.y: 6

T() constr called...
T.x: 0
T.y: 0

which is what you want and can be seen here and here .这就是你想要的,可以在这里这里看到。

Another solution would be to use delegating constructor (as suggested by @MarekR in the comment below) like:另一种解决方案是使用委托构造函数(如@MarekR 在下面的评论中所建议的那样),例如:

T():T(0, 0) 
{
    std::cout << "T() constr called..." << std::endl;
}

Do I understand it correctly, that if I have a constructor defined, it will not perform a zero initialization?我是否正确理解,如果我定义了一个构造函数,它不会执行零初始化?

Yes.是的。

Note that T is not an aggregate because it contains user-provided constructors.请注意, T不是聚合,因为它包含用户提供的构造函数。 As the effect ofvalue initialization :作为值初始化的效果:

  1. if T is a class type with no default constructor or with a user-provided or deleted default constructor, the object is default-initialized;如果 T 是没有默认构造函数或具有用户提供或删除的默认构造函数的类类型,则该对象是默认初始化的;

  2. if T is a class type with a default constructor that is neither user-provided nor deleted (that is, it may be a class with an implicitly-defined or defaulted default constructor), the object is zero-initialized and then it is default-initialized if it has a non-trivial default constructor;如果 T 是具有既不是用户提供也不是删除的默认构造函数的类类型(即,它可能是具有隐式定义或默认默认构造函数的类),则该对象被零初始化,然后是默认的-如果它有一个非平凡的默认构造函数,则初始化;

T contains a user-provided default constructor, then #1 (but not #2 performing zero-initialization firstly) is applied. T包含一个用户提供的默认构造函数,然后应用 #1(但不是 #2 首先执行零初始化)。

In default initialization , the user-provided default constructor is used to initialize the object.默认初始化中,用户提供的默认构造函数用于初始化对象。 The default constructor doesn't perform initialization on data members, they are initialized to indeterminate values.默认构造函数不对数据成员执行初始化,它们被初始化为不确定的值。

Zero initialization is a special case.零初始化是一种特殊情况。 The standard only guarantees member attributes to be default initialized.该标准仅保证成员属性被默认初始化。 For class objects it indeed means that the default constructor will be called.对于类对象,它确实意味着将调用默认构造函数。 But for basic type objects default initialization is just... no initialization at all.但是对于基本类型对象,默认初始化只是......根本没有初始化。 You have to explicitely ask for it if you need it:如果你需要它,你必须明确要求它:

T(): x(0), y(0) {
    ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM