当前位置: 首页 > 知识库问答 >
问题:

C零初始化-为什么这个程序中的b是未初始化的,而a是初始化的?

田鸿彩
2023-03-14

根据此堆栈溢出问题的公认(且唯一)答案,

使用

MyTest() = default;

将改为零初始化对象。

那么,为什么呢?,

#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;
}

生成此输出:

0 32766

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

根据这个问题的公认答案,

如果POD成员未在构造函数中初始化,也未在类初始化中通过C11初始化,则默认为已初始化。

不管是堆栈还是堆,答案都是一样的。

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

尽管我试着围绕默认构造函数和默认初始化(尽管很小),我还是找不出一个解释。

共有3个答案

陈俊郎
2023-03-14

来自cp首选项:

聚合初始化初始化聚合。它是列表初始化的一种形式。

聚合是以下类型之一:

[剪报]

>

  • 类类型[snip],它具有

    >

  • [snip](不同的标准版本有不同的版本)

    没有用户提供、继承或显式构造函数(允许显式默认或删除的构造函数)

    [slp](还有更多的规则,适用于两个类)

    根据这个定义,foo是聚合,而bar不是聚合(它有用户提供的非默认构造函数)。

    因此对于fooT对象{arg1,arg2,…} 是聚合初始化的语法。

    聚合初始化的效果是:

    >

  • [snip](一些与本案无关的细节)

    如果初始化子句的数目小于成员数目或初始化列表完全为空,则对剩余成员进行值初始化。

    因此,a.a是初始化的值,这对于int意味着零初始化。

    对于barT对象{} 是值初始化(类实例的初始化,而不是成员的值初始化!)。由于它是具有默认构造函数的类类型,因此调用默认构造函数。默认定义的默认构造函数初始化成员(由于没有成员初始值设定项),在int(具有非静态存储)的情况下,b.b的值不确定。

    对于pod类型,默认初始化为零初始化。

    不,这是错误的。

    P. S.关于你的实验和你的结论:看到输出为零并不一定意味着变量初始化为零。零是垃圾值完全可能的数字。

    因此,我在发布之前可能运行了5~6次程序,现在大约运行了10次,a始终为零。b变化不大。

    该值多次相同的事实也不一定意味着它已初始化。

    我还尝试了set(CMAKE_CXX_标准14)。结果是一样的。

    多个编译器选项的结果相同并不意味着变量已初始化。(尽管在某些情况下,更改标准版本可能会更改其是否已初始化)。

    我怎么能稍微摇晃一下我的公羊,这样如果那里是零,它现在应该是别的东西了

    在C语言中,没有保证使未初始化的值显示为非零的方法。

    知道变量是否已初始化的唯一方法是将程序与语言的规则进行比较,并验证规则是否表明它已初始化。在这种情况下,a. a确实是初始化的。

  • 孔星宇
    2023-03-14

    行为上的差异来自这样一个事实:根据[dcl.fct.def.default]/5bar::bar是用户提供的,而foo::foo不是1。因此,foo::foo将值初始化其成员(意思是:零初始化foo::a),但bar::bar将保持未初始化状态2

    1)[dcl.fct.def.default]/5

    如果函数是用户声明的,并且在其第一次声明时没有显式默认或删除,则该html" target="_blank">函数是用户提供的。

    2)

    从[dcl.init#6]:

    初始化T类型对象的值意味着:

    >

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

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

    ...

    来自[dcl.init.list]:

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

    >

  • 否则,如果初始化器列表没有元素,并且T是具有默认构造函数的类类型,则对象将进行值初始化。

    从维托里奥·罗密欧的回答

  • 姜嘉荣
    2023-03-14

    这里的问题相当微妙。你会这么想

    bar::bar() = default;
    

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

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

    强调我的

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

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

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

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

     类似资料:
    • 本文向大家介绍tensorflow 初始化未初始化的变量实例,包括了tensorflow 初始化未初始化的变量实例的使用技巧和注意事项,需要的朋友参考一下 今日在Stack Overflow上看到一个问如何只初始化未初始化的变量,有人提供了一个函数,特地粘贴过来共大家品鉴: 通过tf.global_variables()返回一个全局变量的列表global_vars, 然后以python列表解析式的

    • 问题内容: 我们可以将代码放入构造函数或方法或初始化块中。初始化块有什么用?每个Java程序都必须有它吗? 问题答案: 首先,有两种类型的初始化块: 实例初始化块,以及 静态初始化块。 此代码应说明它们的用法以及执行顺序: 印刷品: 如果要运行某些代码而不管使用哪个构造函数,或者想要对匿名类进行一些实例初始化,则实例迭代块很有用。

    • 问题内容: 我在用Java工作。 我通常会这样设置一些对象: 问题是:在此示例中是否等于,按原样我可以假定对未初始化的对象进行空检查将是准确的? 问题答案: 正确,未显式初始化的引用类型的静态成员和实例成员都由Java 设置为。相同的规则适用于数组成员。 根据Java语言规范的第4.12.5节: 变量的初始值 程序中的每个变量在使用值之前都必须具有一个值: 每个类变量,实例变量或数组组件在创建时均

    • 我试图理解@bolov对删除默认构造函数问题的第一个公认答案。对象仍然可以创建......有时[1] 似乎我发现了一个错误,所以它搞乱了整个解释。 @bolov解释了为什么这段代码能够在c 11中成功编译: 场景A 以及为什么这段代码无法在c 11中编译: 场景C 他说,重点是第一个foo是聚合,第二个foo不是聚合。 然后他给出了cppreference的摘录: T类型对象的列表初始化的影响是:

    • 问题内容: 我有这个代码: 这会导致编译错误:可能尚未初始化,这很公平。 现在,我将代码更改为: 我得到同样的编译错误!我必须初始化为null: 那么,不初始化对象和初始化为null有什么区别?如果我声明一个没有初始化的对象,它是否为null? 谢谢 问题答案: 字段(成员变量)被初始化为(或初始化为默认的原始值,如果它们是原始的) 局部变量未初始化,您有责任设置初始值。

    • Initialization 初始化 Although it doesn’t look superficially very different from initialization in C or C++, initialization in Go is more powerful. Complex structures can be built during initialization a