【问题标题】:Does a c++ struct have a default constructor?c++ 结构是否有默认构造函数?
【发布时间】:2011-11-26 16:56:07
【问题描述】:

我写了如下代码sn-p:

void foo()
{
    struct _bar_ 
    {
        int a;
    } bar; 

    cout << "Value of a is " << bar.a;
}

并用 g++ 4.2.1 (Mac) 编译它。输出为“a 的值为 0”。

说 c++ 中结构的数据成员总是默认初始化(与 c 相比)是真的吗?还是观察到的结果只是巧合?

我可以想象 c++ 中的结构有一个默认构造函数(因为 c++ 中的结构和类几乎相同),这可以解释为什么 bar 的数据成员 a 被初始化为零。

【问题讨论】:

  • 正如也指出的,这是一个巧合。请注意,您始终可以使用 bar = {} 对结构进行零初始化。

标签: c++


【解决方案1】:

简单的答案是肯定的。
它有一个默认构造函数。

注意:结构和类是相同的(除了访问说明符的默认状态)。

但它是否初始化成员将取决于实际对象的声明方式。在您的示例中,成员未初始化并且 a 具有不确定的值。

void func()
{
    _bar_  a;                 // Members are NOT initialized.
    _bar_  b = _bar_();       // Members are zero-initialized
    // From C++14
    _bar_  c{};               // New Brace initializer (Members are zero-initialized)


    _bar_* aP = new _bar_;    // Members are NOT initialized.
    _bar_* bP = new _bar_();  // Members are zero-initialized
    // From C++14
    _bar_  cP = new _bar_{};  // New Brace initializer (Members are zero-initialized)
}

// static storage duration objects
//   i.e. objects at the global scope.
_bar_ c; // Members are zero-initialized.

具体细节在标准8.5 Initializers [dcl.init] 第 4-10 段中进行了解释。但以下是对这种情况的简单总结。

没有用户定义构造函数的结构具有编译器生成的构造函数。但是它的作用取决于它是如何使用的,它要么默认初始化其成员(对于 POD 类型通常什么都没有),要么它可能将其成员初始化为零(对于 POD 通常意味着将其成员设置为零)。

PS。不要使用 _ 作为类型名称的第一个字符。你会遇到问题。

【讨论】:

  • 一个下划线是可以的,除非后面跟着另一个下划线或大写。
  • 我选择了这个答案,因为它最好地回答了我的问题。它还提供了有关默认构造函数何时对数据成员进行零初始化的其他信息。
  • @rubenvb:实际上这不是真的。阅读:what-are-the-rules-about-using-an-underscore-in-a-c-identifier 问题是大多数人不知道确切的规则并且会犯这样的错误。所以最好在标识符的开头避免它们。这里:下划线后跟任何字母在全局范围内保留。
  • @ShravyaBoggarapu:是的。 注意 1: 如果一个对象 id 零初始化 它会调用任何对象成员的默认构造函数。如果该对象没有显式构造函数,那么它将使用编译器生成的构造函数零初始化注意 2: 如果一个对象 id default-initialized 它会调用任何对象成员的默认构造函数。如果该对象没有显式构造函数,那么它将使用编译器生成的构造函数默认初始化
  • @AlessandroJacopson:在n4800。第 10.9 节第 1 段告诉您阅读第 9.3 节。在第 9.3 节第 11 节An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized. 然后值初始化在第 9.3 节第 8.2 节中定义。 if T is a ... class type without a user-provided or deleted default constructor, then the object is zero-initialized 然后零初始化在第 9.3 节第 6.2 段中定义 if T is a ... non-union class type, its padding bits (6.7) are initialized to zero bits
【解决方案2】:

说 c++ 中结构的数据成员总是默认初始化(与 c 相比)是真的吗?还是观察到的结果只是巧合?

这是巧合。

您的代码调用未定义行为;除非您将成员明确设置为 0,否则它们可以是任何东西。

【讨论】:

  • “未指定”还是“未定义”? bar.a 是一个有效变量,它只是处于不确定状态。
  • @KerrekSB: bar.a 是具有Undefined Value 的有效变量。
【解决方案3】:

不是一个答案,但你可能会认为它是......如果你想尝试一下:

void foo() {
   struct test {
      int value;
   } x;
   std::cout << x.value << std::endl;
   x.value = 1000;
}
int main() {
   foo();
   foo();
}

在您的示例中,内存在创建变量之前已经具有 0 值,因此您可以称其为 幸运巧合(事实上,某些操作系统会在开始之前将所有内存清零一个进程,这意味着 0 很可能在一个小程序中找到......),前面的代码将调用该函数两次,并且第一次调用的内存将在第二次调用中重用,机会是第二次将打印 1000。但是请注意,该值仍未定义,并且此测试可能会或不会显示预期结果(即编译器可以做很多事情并且会产生不同的结果... )

【讨论】:

    【解决方案4】:

    结构的成员变量默认情况下没有初始化。就像一个类(因为结构和类完全一样,只是在结构中成员默认是公共的)。

    【讨论】:

    • 它们总是“初始化”,但有时初始化什么都不做。
    【解决方案5】:

    不要依赖这个非标准的功能

    添加

    foo() : a() {}
    

    我不记得 gcc 4.2 的确切状态(我认为它太旧了),但如果您使用的是 C++11,您可以执行以下操作

    foo()=default;
    

    【讨论】:

    • 他能做什么foo()=default;
    • @JS:它只是提供了一种简单的方法来默认将结构的所有数据成员大写,如果这是他想要的,那么这是一个很好的方法(如果他的编译器支持它)
    猜你喜欢
    • 2012-06-30
    • 2014-02-05
    • 1970-01-01
    • 2014-05-15
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 2020-05-14
    相关资源
    最近更新 更多