C++ 零初始化 - 为什么这个程序中的 `b` 未初始化,但 `a` 已初始化? [英] C++ zero initialization - Why is `b` in this program uninitialized, but `a` is initialized?

查看:23
本文介绍了C++ 零初始化 - 为什么这个程序中的 `b` 未初始化,但 `a` 已初始化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据这个 Stack Overflow 问题的已接受(且唯一)答案,

<块引用>

定义构造函数

MyTest() = 默认值;

将对对象进行零初始化.

那为什么会出现以下情况,

#include <iostream>结构富{foo() = 默认值;诠释一个;};结构栏{酒吧();诠释 b;};bar::bar() = 默认值;int main() {富一个{};酒吧 b{};std::cout <<a.a <<' ' <<b.b;}

产生这个输出:

0 32766

定义的两个构造函数都是默认的?对?而对于 POD 类型,默认初始化是零初始化.

并根据 这个问题,

<块引用>

  1. 如果 POD 成员未在构造函数中或通过 C++11 初始化类内初始化,默认初始化.

  2. 无论栈还是堆,答案都是一样的.

  3. 在 C++98(而不是之后)中,new int() 被指定为执行零初始化.

尽管试图将我的(尽管 )头绕在 默认构造函数默认初始化,我想不出一个解释.

解决方案

这里的问题非常微妙.你会认为

bar::bar() = 默认值;

会给你一个编译器生成的默认构造函数,它确实如此,但它现在被认为是用户提供的.[dcl.fct.def.default]/5状态:

<块引用>

显式默认函数和隐式声明函数统称为默认函数,实现应为它们提供隐式定义([class.ctor] [class.dtor]、[class.copy.ctor]、[class.copy.assign]),这可能意味着将它们定义为已删除.如果一个函数是用户声明的,并且在其第一次声明时没有显式默认或删除,则该函数是用户提供的. 定义了用户提供的显式默认函数(即,在其第一次声明后显式默认)在它被明确默认的地方;如果这样的函数被隐式定义为已删除,则程序格式错误.[ 注意:在第一次声明后将函数声明为默认函数可以提供高效的执行和简洁的定义,同时为不断发展的代码库提供稳定的二进制接口.— 尾注 ]

强调我的

所以我们可以看到,由于您在第一次声明时没有默认 bar(),现在它被认为是用户提供的.正因为如此 [dcl.init]/8.2

<块引用>

如果 T 是一个(可能是 cv 限定的)类类型,没有用户提供或删除的默认构造函数,则该对象为零初始化并检查默认初始化的语义约束,如果 T 具有非平凡的默认构造函数,对象是默认初始化的;

不再适用,我们不是初始化 b 而是默认按 [dcl.init]/8.1

<块引用>

如果 T 是没有默认构造函数 ([class.default.ctor]) 或用户提供或删除的默认构造函数的(可能是 cv 限定的)类类型 ([class]),则对象为默认初始化;

According to the accepted (and only) answer for this Stack Overflow question,

Defining the constructor with

MyTest() = default;

will instead zero-initialize the object.

Then why does the following,

#include <iostream>

struct foo {
    foo() = default;
    int a;
};

struct bar {
    bar();
    int b;
};

bar::bar() = default;

int main() {
    foo a{};
    bar b{};
    std::cout << a.a << ' ' << b.b;
}

produce this output:

0 32766

Both constructors defined are default? Right? And for POD types, the default initialization is zero-initialization.

And according to the accepted answer for this question,

  1. If a POD member is not initialized in the constructor nor via C++11 in-class initialization, it is default-initialized.

  2. The answer is the same regardless of stack or heap.

  3. In C++98 (and not afterward), new int() was specified as performing zero initialization.

Despite trying to wrap my (albeit tiny) head around default constructors and default initialization, I couldn't come up with an explanation.

解决方案

The issue here is pretty subtle. You would think that

bar::bar() = default;

would give you a compiler generated default constructor, and it does, but it is now considered user provided. [dcl.fct.def.default]/5 states:

Explicitly-defaulted functions and implicitly-declared functions are collectively called defaulted functions, and the implementation shall provide implicit definitions for them ([class.ctor] [class.dtor], [class.copy.ctor], [class.copy.assign]), which might mean defining them as deleted. A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration. A user-provided explicitly-defaulted function (i.e., explicitly defaulted after its first declaration) is defined at the point where it is explicitly defaulted; if such a function is implicitly defined as deleted, the program is ill-formed. [ Note: Declaring a function as defaulted after its first declaration can provide efficient execution and concise definition while enabling a stable binary interface to an evolving code base. — end note ]

emphasis mine

So we can see that since you did not default bar() when you first declared it, it is now considered user provided. Because of that [dcl.init]/8.2

if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;

no longer applies and we are not value initializing b but instead default initializing it per [dcl.init]/8.1

if T is a (possibly cv-qualified) class type ([class]) with either no default constructor ([class.default.ctor]) or a default constructor that is user-provided or deleted, then the object is default-initialized;

这篇关于C++ 零初始化 - 为什么这个程序中的 `b` 未初始化,但 `a` 已初始化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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