首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有复制列表初始化器的C++对象初始化

具有复制列表初始化器的C++对象初始化
EN

Stack Overflow用户
提问于 2021-11-02 09:50:47
回答 3查看 131关注 0票数 4
代码语言:javascript
复制
// 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();
}

我得到的结果如下:

代码语言:javascript
复制
T(x,y) constr called...
T.x: 5
T.y: 6

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

t2实例的成员不是零初始化的(我想要实现的)。我是否正确理解,如果我定义了一个构造函数,它将不会执行零初始化?(我知道如何使用显式默认值实现初始化为零。问题是为什么我不能使用init列表)

列表初始化

否则,如果大括号-init-列表为空且T是具有默认构造函数的类类型,则执行值初始化。

值初始化

在所有情况下,如果使用空大括号{}且T是聚合类型,则执行聚合初始化而不是值初始化。

聚合-初始化(这似乎不是我的情况,因此它没有将成员初始化为零)

聚合是下列类型之一:

  • 类类型(通常是结构类型或联合类型),具有
    • 没有用户声明的构造函数。

什么是最简单和较少错误的旧代码修改,在这里,我需要解决一些类成员在初始化前被使用的问题?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-11-02 10:39:45

我是否正确理解,如果我定义了一个构造函数,它将不会执行零初始化?

是。

请注意,T不是聚合的,因为它包含用户提供的构造函数。作为值初始化的作用

  1. 如果T是一个没有默认构造函数或用户提供或删除的默认构造函数的类类型,则该对象是默认初始化的;
  2. 如果T是一个类类型,它的默认构造函数既不是用户提供的,也不是删除的(也就是说,它可以是一个具有隐式定义的或默认的默认构造函数的类),则该对象是零初始化的,如果它有一个非平凡的默认构造函数,则为默认初始化;

T包含用户提供的默认构造函数,然后应用#1 (但不是首先执行零初始化的#2 )。

默认初始化中,用户提供的默认构造函数用于初始化对象.默认构造函数不对数据成员执行初始化,而是将其初始化为不确定值。

票数 3
EN

Stack Overflow用户

发布于 2021-11-02 09:55:24

t2的数据成员具有垃圾值。这是因为它们是内置类型的,而您并没有显式地将它们降级。解决办法是:

解决方案1:使用构造函数初始化程序列表

代码语言:javascript
复制
T(): x(0), y(0){
        std::cout << "T() constr called..." << std::endl;
    };

解决方案2:使用类内初始化器

代码语言:javascript
复制
int x = 0, y = 0;

这就是为什么建议

始终在块/本地范围内初始化内置类型。

如果您使用上述任何一个给定的解决方案,则输出如下:

代码语言:javascript
复制
T(x,y) constr called...
T.x: 5
T.y: 6

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

这就是你想要的,可以看到这里这里

另一种解决方案是使用委托构造函数(如@MarekR在下面的注释中所建议的那样)如下:

代码语言:javascript
复制
T():T(0, 0) 
{
    std::cout << "T() constr called..." << std::endl;
}
票数 3
EN

Stack Overflow用户

发布于 2021-11-02 10:07:14

零初始化是一种特例。标准只保证默认初始化成员属性。对于类对象,这实际上意味着将调用默认构造函数。但是对于基本类型对象,默认初始化只是..。根本没有初始化。如果你需要它,你必须明确地要求它:

代码语言:javascript
复制
T(): x(0), y(0) {
    ...
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69808364

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档