繁体   English   中英

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

[英]c++ implicit class member initialization for (POD struct, POD class and POD) members

我试图理解隐式类成员初始化如何为成员{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 struct,POD classes和POD}成员的隐式初始化时它是UB。 任何帮助将不胜感激... :)

构造函数很复杂,细节是技术性的,但这里是一个通用的摘要*:

有三种方法可以初始化:

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

他们在许多情况下被召唤:

  • static globals - Zero Initialized,然后Value Initialized。 (非常奇怪)
  • locals - 默认初始化。
  • new T; - 默认初始化
  • new T(); - 值初始化
  • 成员不在初始列表中 - 默认初始化
  • init列表中的成员 - 值Initialize。

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

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

*我的摘要在技术上并不准确,但对于大多数实际代码而言足够准确。 例如,数组在技术上有特殊的规则,但它们非常直观,不值得一提。

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

暂无
暂无

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

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