初始化C ++结构的正确方法


82

我们的代码涉及一个POD(普通旧数据结构)结构(这是一个基本的c ++结构,其中包含其他结构和POD变量,需要在开始时对其进行初始化。)

根据我所读的文章,似乎:

myStruct = (MyStruct*)calloc(1, sizeof(MyStruct));

应该将所有值初始化为零,如下所示:

myStruct = new MyStruct();

但是,当用第二种方法初始化该结构时,Valgrind随后抱怨说,当使用这些变量时,“条件跳转或移动取决于未初始化的值”。我的理解是否存在缺陷,还是Valgrind抛出假阳性?


1
另外,请注意,new MyStruct()在C ++ 03中不需要设置任何填充字节。在C ++ 0x中是。在C ++ 0x中,任何填充位都将设置为0。
Johannes Schaub-litb 2011年

感谢您的帮助,我编辑了问题。
Shadow503

相关型号常见问题:stackoverflow.com/questions/620137/...
Robᵩ

据我了解,您不应收到该错误消息。也许您的数据结构不是POD?您可以将代码缩减为仍能证明这种行为的最小程序,然后发布该简化程序吗?(请参阅sscce.org)。
罗伯(Robᵩ)2011年

什么编译器?您可以发布MyStruct的定义吗?
艾伦·斯托克斯

Answers:


120

在C ++中,类/结构是相同的(在初始化方面)。

非POD结构也可以具有构造函数,以便可以初始化成员。
如果您的结构是POD,则可以使用初始化程序。

struct C
{
    int x; 
    int y;
};

C  c = {0}; // Zero initialize POD

另外,您可以使用默认构造函数。

C  c = C();      // Zero initialize using default constructor
C  c{};          // Latest versions accept this syntax.
C* c = new C();  // Zero initialize a dynamically allocated object.

// Note the difference between the above and the initialize version of the constructor.
// Note: All above comments apply to POD structures.
C  c;            // members are random
C* c = new C;    // members are random (more officially undefined).

我相信valgrind会抱怨,因为那是C ++过去的工作方式。(我不确定何时使用零初始化默认构造升级C ++)。最好的选择是添加一个初始化对象的构造函数(允许使用构造函数)。

附带说明:
许多初学者尝试珍惜init:

C c(); // Unfortunately this is not a variable declaration.
C c{}; // This syntax was added to overcome this confusion.

// The correct way to do this is:
C c = C();

快速搜索“最令人烦恼的解析”将提供比我更好的解释。


1
您对C ++中的变量零初始化有参考吗?最后我听说,它仍然具有与C. IIRC相同的行为。MSVC编译器甚至在某个时刻放弃了零初始化未初始化的成员(出于性能原因,我认为),这显然给其他MS部门造成了相当严重的问题:)
Marc Mutz-mmutz,2011年

1
不,C()但是看来您是对的
Marc Mutz-mmutz,2011年

4
随着POD类TT()始终初始化为零标子对象。在C ++ 98中,顶层初始化的名称被称为与在C ++ 03中不同(“默认初始化”与“值初始化”),但是POD的最终效果是相同的。C ++ 98和C ++ 03的所有值都为零。
约翰内斯·绍布

1
C c();不幸的是,@ RockyRaccoon不是变量声明,而是函数的前向声明(一个名为“ c”的函数,它不带参数并且返回类型为C的对象)。Google:最令人讨厌的解析
马丁·约克

1
@RockyRaccoon此处以及您在评论中链接到的问题的区别;是在这种情况下,构造函数中没有使用任何参数。因此,编译器很难解析它并告诉变量声明和函数的正向声明之间的区别。它选择前向函数声明。如果在构造函数中需要参数,则编译器可以看到这是一个变量声明,没有任何问题。C c(4);是有效的变量声明。
马丁·约克

2

根据您告诉我们的信息,它在valgrind中似乎是错误的肯定。假定对象是POD,则newwith的语法()应将其值初始化。

是否有可能您的结构的某些子部分实际上不是POD,从而阻止了预期的初始化?您是否可以将代码简化为仍可标记valgrind错误的可发布示例?

或者,也许您的编译器实际上并未对POD结构进行值初始化。

在任何情况下,最简单的解决方案可能是根据struct / subparts的需要编写构造函数。


1

我写一些测试代码:

#include <string>
#include <iostream>
#include <stdio.h>

using namespace std;

struct sc {
    int x;
    string y;
    int* z;
};

int main(int argc, char** argv)
{
   int* r = new int[128];
   for(int i = 0; i < 128; i++ ) {
        r[i] = i+32;
   }
   cout << r[100] << endl;
   delete r;

   sc* a = new sc;
   sc* aa = new sc[2];
   sc* b = new sc();
   sc* ba = new sc[2]();

   cout << "az:" << a->z << endl;
   cout << "bz:" << b->z << endl;
   cout << "a:" << a->x << " y" << a->y << "end" << endl;
   cout << "b:" << b->x << " y" << b->y <<  "end" <<endl;
   cout << "aa:" << aa->x << " y" << aa->y <<  "end" <<endl;
   cout << "ba:" << ba->x << " y" << ba->y <<  "end" <<endl;
}

g ++编译并运行:

./a.out 
132
az:0x2b0000002a
bz:0
a:854191480 yend
b:0 yend
aa:854190968 yend
ba:0 yend

好的,我对new sc;vs不太熟悉new sc();。我本以为缺少的括号是个错误。但这似乎表明答案是正确的(当您使用默认构造函数时,它会将init初始化为0。)
nycynik

0

您需要初始化结构中具有的任何成员,例如:

struct MyStruct {
  private:
    int someInt_;
    float someFloat_;

  public:
    MyStruct(): someInt_(0), someFloat_(1.0) {} // Initializer list will set appropriate values

};

在这种情况下,我不是在使用类,而是在使用struct。
Shadow503

结构是一类。编辑了我的帖子:)
ralphtheninja 2011年

2
您不需要为POD执行此操作
艾伦·斯托克斯

0

由于它是POD结构,因此您始终可以将其设置为0-这可能是初始化字段的最简单方法(假设合适)。


1
无论是结构还是类都与memset或创建构造函数的能力无关。参见例如stackoverflow.com/questions/2750270/cc-struct-vs-class
Erik

创建类后,通常不会再对其进行记忆设置,因为它的构造函数(大概是)进行了初始化。
Scott C Wilson

1
除了默认保护(分别为私有和公共)外,C ++中的“类”和“结构”之间没有区别。结构可以是非POD,类可以是POD,这些概念是正交的。
Marc Mutz-mmutz 2011年

@mmutz和@Erik-同意-缩短了我的回答以防止混淆。
斯科特·威尔逊

memset()并非最佳选择,您可以通过仅调用其默认ctor来将POD结构零初始化。
尼尔斯

0

在我看来,这是最简单的方法。可以使用花括号“ {}”来初始化结构成员。例如,以下是有效的初始化。

struct Point 
{ 
   int x, y; 
};  

int main() 
{ 
   // A valid initialization. member x gets value 0 and y 
   // gets value 1.  The order of declaration is followed. 
   struct Point p1 = {0, 1};  
}

在c ++中有关于结构的良好信息-https: //www.geeksforgeeks.org/structures-in-cpp/

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.