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

发布于 2024-11-05 08:57:51 字数 445 浏览 5 评论 0原文

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

基于我的 阅读,似乎:

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

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

myStruct = new MyStruct();

但是,当在中初始化结构时第二种方式,当使用这些变量时,Valgrind 后来抱怨“条件跳转或移动取决于未初始化的值”。我的理解是否有缺陷,或者 Valgrind 是否抛出误报?

Our code involves a POD (Plain Old Datastructure) struct (it is a basic c++ struct that has other structs and POD variables in it that needs to get initialized in the beginning.)

Based one what I've read, it seems that:

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

should initialize all the values to zero, as does:

myStruct = new MyStruct();

However, when the struct is initialized in the second way, Valgrind later complains "conditional jump or move depends on uninitialised value(s)" when those variables are used. Is my understanding flawed here, or is Valgrind throwing false positives?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

地狱即天堂 2024-11-12 08:57:51

在 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();

快速搜索“Most Veshing Parse”将提供比我更好的解释。

In C++ classes/structs are identical (in terms of initialization).

A non POD struct may as well have a constructor so it can initialize members.
If your struct is a POD then you can use an initializer.

struct C
{
    int x; 
    int y;
};

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

Alternatively you can use the default constructor.

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).

I believe valgrind is complaining because that is how C++ used to work. (I am not exactly sure when C++ was upgraded with the zero initialization default construction). Your best bet is to add a constructor that initializes the object (structs are allowed constructors).

As a side note:
A lot of beginners try to value 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();

A quick search for the "Most Vexing Parse" will provide a better explanation than I can.

热血少△年 2024-11-12 08:57:51

我写了一些测试代码:

#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

I write some test code:

#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++ compile and run:

./a.out 
132
az:0x2b0000002a
bz:0
a:854191480 yend
b:0 yend
aa:854190968 yend
ba:0 yend
死开点丶别碍眼 2024-11-12 08:57:51

根据您告诉我们的情况,这似乎是 valgrind 中的误报。带有 ()new 语法应该对对象进行值初始化(假设它是 POD)。

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

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

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

From what you've told us it does appear to be a false positive in valgrind. The new syntax with () should value-initialize the object, assuming it is POD.

Is it possible that some subpart of your struct isn't actually POD and that's preventing the expected initialization? Are you able to simplify your code into a postable example that still flags the valgrind error?

Alternately perhaps your compiler doesn't actually value-initialize POD structures.

In any case probably the simplest solution is to write constructor(s) as needed for the struct/subparts.

蒗幽 2024-11-12 08:57:51
    You can declare and initalise structure in C++ this way also:::
    
    struct person{
        int a,h;
     
        person(int a1,int h1): a(a1),h(h1){
            
        }// overriden methods

        person():a(0),h(0){
            
        }// by default
    };

   struct person p; 
   --> This creates from by default Person Age: 0 height: 0

   struct person p = person(3,33);  
    --> This creates from overriden methods Person Age: 3 height: 33
     

     
    You can declare and initalise structure in C++ this way also:::
    
    struct person{
        int a,h;
     
        person(int a1,int h1): a(a1),h(h1){
            
        }// overriden methods

        person():a(0),h(0){
            
        }// by default
    };

   struct person p; 
   --> This creates from by default Person Age: 0 height: 0

   struct person p = person(3,33);  
    --> This creates from overriden methods Person Age: 3 height: 33
     

     
星軌x 2024-11-12 08:57:51

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

Since it's a POD struct, you could always memset it to 0 - this might be the easiest way to get the fields initialized (assuming that is appropriate).

红衣飘飘貌似仙 2024-11-12 08:57:51

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

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/structurals-在cpp中/

That seems to me the easiest way. Structure members can be initialized using curly braces ‘{}’. For example, following is a valid initialization.

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

There is good information about structs in c++ - https://www.geeksforgeeks.org/structures-in-cpp/

§对你不离不弃 2024-11-12 08:57:51

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

struct MyStruct {
  private:
    int someInt_;
    float someFloat_;

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

};

You need to initialize whatever members you have in your struct, e.g.:

struct MyStruct {
  private:
    int someInt_;
    float someFloat_;

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

};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文