gpt4 book ai didi

(POD结构,POD类和POD)成员的c++隐式类成员初始化

转载 作者:太空狗 更新时间:2023-10-29 20:58:30 25 4
gpt4 key购买 nike

我试图了解隐式类成员初始化如何对成员 {POD 结构、POD 类和 POD} 起作用。稍微阅读后,我希望它们被初始化为默认值,但实际行为似乎有所不同 -

#include <iostream>

struct S1
{
void* a;
int b;
};

struct S2
{
S2() { std::cout << "!"; }
void* a;
int b;
};

struct S3
{
S3() : a(), b() { std::cout << "!"; }
void* a;
int b;
};

class C1
{
public:
void* a;
int b;
};

class C2
{
public:
C2() { std::cout << "!"; }
void* a;
int b;
};

class C3
{
public:
C3() : a(), b() { std::cout << "!"; }
void* a;
int b;
};


template <typename T>
class FOO1
{
public:
T s;
int a;
};

template <typename T>
class FOO2
{
public:
FOO2() {}
T s;
int a;
};

template <typename T>
class FOO3
{
public:
FOO3() : s(), a() {}
T s;
int a;
};

//#define SKIP_S1C1

template <typename T>
void moo()
{
#ifndef SKIP_S1C1
T* f = new T();
T foo = *f;
std::cout << ":\ts = (" << foo.s.a << ", " << foo.s.b << ")\ta = " << foo.a << std::endl;
delete f;
#else
T foo;
std::cout << ":\ts = (" << foo.s.a << ", " << foo.s.b << ")\ta = " << foo.a << std::endl;
#endif
}


int main()
{
#ifndef SKIP_S1C1
moo<FOO1<S1> >();
#endif
moo<FOO1<S2> >();
moo<FOO1<S3> >();
#ifndef SKIP_S1C1
moo<FOO1<C1> >();
#endif
moo<FOO1<C2> >();
moo<FOO1<C3> >();

std::cout << std::endl;

#ifndef SKIP_S1C1
moo<FOO2<S1> >();
#endif
moo<FOO2<S2> >();
moo<FOO2<S3> >();
#ifndef SKIP_S1C1
moo<FOO2<C1> >();
#endif
moo<FOO2<C2> >();
moo<FOO2<C3> >();

std::cout << std::endl;

#ifndef SKIP_S1C1
moo<FOO3<S1> >();
#endif
moo<FOO3<S2> >();
moo<FOO3<S3> >();
#ifndef SKIP_S1C1
moo<FOO3<C1> >();
#endif
moo<FOO3<C2> >();
moo<FOO3<C3> >();
}

明显的运行结果不足以说明 POD 是否已初始化为其默认值 0 或仅包含噪声。但无论如何,这里有一些结果:

使用 gcc 4.6.3 在 ubuntu 上构建并运行它 #define SKIP_S1C1 未注释,我明白了

!:      s = (0x7ffffe557770, 4196620)   a = 1
!: s = (0, 0) a = 1
!: s = (0, 0) a = 1
!: s = (0, 0) a = 1

!: s = (0x1, 6299744) a = 6299744
!: s = (0, 0) a = 6299744
!: s = (0, 0) a = 6299744
!: s = (0, 0) a = 6299744

!: s = (0x1, 6299744) a = 0
!: s = (0, 0) a = 0
!: s = (0, 0) a = 0
!: s = (0, 0) a = 0

然后把它注释掉,我明白了

:       s = (0, 0)      a = 0
!: s = (0, 0) a = 0
!: s = (0, 0) a = 0
: s = (0, 0) a = 0
!: s = (0, 0) a = 0
!: s = (0, 0) a = 0

: s = (0, 0) a = 0
!: s = (0, 0) a = 0
!: s = (0, 0) a = 0
: s = (0, 0) a = 0
!: s = (0, 0) a = 0
!: s = (0, 0) a = 0

: s = (0, 0) a = 0
!: s = (0, 0) a = 0
!: s = (0, 0) a = 0
: s = (0, 0) a = 0
!: s = (0, 0) a = 0
!: s = (0, 0) a = 0

在 VS2013 中,加上注释,

:       s = (00000000, 0)       a = 0
!: s = (CDCDCDCD, -842150451) a = -842150451
!: s = (00000000, 0) a = -842150451
: s = (00000000, 0) a = 0
!: s = (00000000, 0) a = 0
!: s = (00000000, 0) a = 0

: s = (CDCDCDCD, -842150451) a = -842150451
!: s = (CDCDCDCD, -842150451) a = -842150451
!: s = (00000000, 0) a = -842150451
: s = (00000000, 0) a = 0
!: s = (00000000, 0) a = 0
!: s = (00000000, 0) a = 0

: s = (00000000, 0) a = 0
!: s = (CDCDCDCD, -842150451) a = 0
!: s = (00000000, 0) a = 0
: s = (00000000, 0) a = 0
!: s = (00000000, 0) a = 0
!: s = (00000000, 0) a = 0

未注释,

!:      s = (CCCCCCCC, -858993460)      a = -858993460
!: s = (00000000, 0) a = -858993460
!: s = (00000000, 0) a = 0
!: s = (00000000, 0) a = 0

!: s = (CCCCCCCC, -858993460) a = -858993460
!: s = (00000000, 0) a = -858993460
!: s = (00000000, 0) a = 0
!: s = (00000000, 0) a = 0

!: s = (CCCCCCCC, -858993460) a = 0
!: s = (00000000, 0) a = 0
!: s = (00000000, 0) a = 0
!: s = (00000000, 0) a = 0

我真的很想了解在 {POS 结构、POD 类和 POD} 成员的隐式初始化方面我应该期待什么以及什么时候是 UB。任何帮助将不胜感激...... :)

最佳答案

构造函数很复杂,细节也很技术性,但这里有一个通用的总结*:

初始化的三种方式:

  • 零初始化 - 细节是技术性的,但有效地将所有位设置为零。这绕过了构造函数
  • Default Initialize - 如果它有构造函数,则调用默认构造函数。否则,不会发生初始化。 从这些中读取是您找到的 UB。
  • Value Initialize - 如果它有构造函数,则调用默认构造函数。否则,它的位全部(有效地)设置为零。

在很多情况下都会调用它们:

  • 静态全局变量 - 零初始化,然后初始化值。 (很奇怪)
  • locals - 默认初始化。
  • new T; - 默认初始化
  • new T(); - 值初始化
  • 成员不在初始化列表中 - 默认初始化
  • 初始化列表中的成员 - 值初始化。

有关更多详细信息,请参阅 C++11 草案中的 §8.5 和 §12.6 节。它们又长又无聊。

另请注意,C 的规则在技术上有惊人的不同,尽管效果对我来说是一样的。

*我的总结在技术上并不准确,但对于大多数真实代码来说已经足够准确了。例如,数组在技术上有特殊的规则,但它们非常直观,不值得一提。

** 是的,它的“初始化”是“未初始化”,这使得其他关于“如果已初始化”的段落在技术上含糊不清,但适用于常识。它没有被初始化。

关于(POD结构,POD类和POD)成员的c++隐式类成员初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27492290/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com