内存中 C++ 对象的结构与结构

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/422830/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 15:16:15  来源:igfitidea点击:

Structure of a C++ Object in Memory Vs a Struct

c++struct

提问by hhafez

If I have a class as follows

如果我有一个类如下

   class Example_Class 
   {
       private:
         int x; 
         int y; 
       public: 
         Example_Class() 
         { 
             x = 8;
             y = 9;
         }
       ~Example_Class() 
       { } 
   };

And a struct as follows

和一个结构如下

struct
{
   int x;
   int y;
} example_struct;

Is the structure in memory of the example_structsimmilar to that in Example_Class

记忆中的结构是否 example_struct类似于Example_Class

for example if I do the following

例如,如果我执行以下操作

struct example_struct foo_struct;
Example_Class foo_class = Example_Class();

memcpy(&foo_struct, &foo_class, sizeof(foo_struct));

will foo_struct.x = 8and foo_struct.y = 9(ie: the same values as the x,y values in the foo_class) ?

foo_struct.x = 8foo_struct.y = 9(即:与 foo_class 中的 x,y 值相同的值)?

The reason I ask is I have a C++ library (don't want to change it) that is sharing an object with C code and I want to use a struct to represent the object coming from the C++ library. I'm only interested in the attributes of the object.

我问的原因是我有一个 C++ 库(不想更改它),它与 C 代码共享一个对象,我想使用一个结构来表示来自 C++ 库的对象。我只对对象的属性感兴趣。

I know the ideal situation would be to have Example_class wrap arround a common structure between the C and C++ code but it is not going to be easy to change the C++ library in use.

我知道理想的情况是让 Example_class 环绕 C 和 C++ 代码之间的公共结构,但更改正在使用的 C++ 库并不容易。

回答by j_random_hacker

The C++ standard guaranteesthat memory layouts of a C structand a C++ class(or struct-- same thing) will be identical, provided that the C++ class/structfits the criteria of being POD("Plain Old Data"). So what does POD mean?

C++ 标准保证Cstruct和 C++ class(或struct——同样的东西)的内存布局将是相同的,前提是 C++ class/struct符合POD(“普通旧数据”)的标准。那么POD是什么意思呢?

A class or struct is POD if:

如果满足以下条件,类或结构就是 POD:

  • All data members are public and themselves POD or fundamental types (but not reference or pointer-to-member types), or arrays of such
  • It has no user-defined constructors, assignment operators or destructors
  • It has no virtual functions
  • It has no base classes
  • 所有数据成员都是公共的,它们本身是 POD 或基本类型(但不是引用或成员指针类型),或此类的数组
  • 它没有用户定义的构造函数、赋值运算符或析构函数
  • 它没有虚函数
  • 它没有基类

About the only "C++-isms" allowed are non-virtual member functions, static members and member functions.

关于唯一允许的“C++-isms”是非虚拟成员函数、静态成员和成员函数。

Since your class has both a constructor and a destructor, it is formally speaking not of POD type, so the guarantee does not hold. (Although, as others have mentioned, in practice the two layouts are likely to be identical on any compiler that you try, so long as there are no virtual functions).

由于您的类同时具有构造函数和析构函数,因此它在形式上不是 POD 类型,因此保证不成立。(尽管正如其他人所提到的,在实践中,只要没有虚函数,这两种布局在您尝试的任何编译器上可能是相同的)。

See section [26.7] of the C++ FAQ Litefor more details.

有关更多详细信息,请参阅C++ FAQ Lite 的[26.7] 部分。

回答by ChrisW

Is the structure in memory of the example_struct simmilar to that in Example_Class

example_struct 在内存中的结构是否与 Example_Class 中的结构相似

The behaviour isn't guaranteed, and is compiler-dependent.

该行为不能保证,并且依赖于编译器。

Having said that, the answer is "yes, on my machine", provided that the Example_Class contains no virtual method (and doesn't inherit from a base class).

话虽如此,答案是“是的,在我的机器上”,前提是 Example_Class 不包含虚拟方法(并且不从基类继承)。

回答by Greg Hewgill

In the case you describe, the answer is "probably yes". However, if the class has any virtual functions (including virtual destructor, which could be inherited from a base class), or uses multiple inheritance then the class layout may be different.

在您描述的情况下,答案是“可能是”。但是,如果该类具有任何虚函数(包括可以从基类继承的虚析构函数),或者使用多重继承,则类布局可能会有所不同。

回答by Nick

To add to what other people have said (eg: compiler-specific, will likely work as long as you don't have virtual functions):

添加其他人所说的内容(例如:特定于编译器的,只要您没有虚函数就可能工作):

I would highly suggest a static assert (compile-time check) that the sizeof(Example_class) == sizeof(example_struct) if you are doing this. See BOOST_STATIC_ASSERT, or the equivalent compiler-specific or custom construction. This is a good first-line of defense if someone (or something, such as a compiler change) modifies the class to invalidate the match. If you want extra checking, you can also runtime check that the offsets to the members are the same, which (together with the static size assert) will guarantee correctness.

如果你这样做,我强烈建议一个静态断言(编译时检查),即 sizeof(Example_class) == sizeof(example_struct)。请参阅 BOOST_STATIC_ASSERT,或等效的特定于编译器或自定义构造。如果有人(或某事,例如编译器更改)修改类以使匹配无效,则这是一个很好的第一道防线。如果您需要额外检查,您还可以运行时检查成员的偏移量是否相同,这(与静态大小断言一起)将保证正确性。

回答by Zoran Horvat

In the early days of C++ compilers there were examples when compiler first changes struct keywords with class and then compiles. So much about similarities.

在 C++ 编译器的早期,有一些例子,编译器首先用 class 更改 struct 关键字,然后再编译。关于相似之处太多了。

Differences come from class inheritance and, especially, virtual functions. If class contains virtual functions, then it must have a pointer to type descriptor at the beginning of its layout. Also, if class B inherits from class A, then class A's layout comes first, followed by class B's own layout.

差异来自类继承,尤其是虚函数。如果类包含虚函数,那么它必须在其布局的开头有一个指向类型描述符的指针。此外,如果 B 类继承自 A 类,则首先是 A 类的布局,然后是 B 类自己的布局。

So the precise answer to your question about just casting a class instance to a structure instance is: depends on class contents. For particular class which has methods (constructor and non-virtual destructor), the layout is probably going to be the same. Should the destructor be declared virtual, the layout would definitely become different between structure and class.

因此,关于将类实例强制转换为结构实例的问题的准确答案是:取决于类内容。对于具有方法(构造函数和非虚拟析构函数)的特定类,布局可能会相同。如果析构函数被声明为虚拟,结构和类之间的布局肯定会变得不同。

Here is an article which shows that there is not much needed to do to step from C structures to C++ classes: Lesson 1 - From Structure to Class

这是一篇文章,表明从 C 结构到 C++ 类不需要做太多工作:第 1 课 - 从结构到类

And here is the article which explains how virtual functions table is introduced to classes that have virtual functions: Lesson 4 - Polymorphism

这是解释如何将虚函数表引入具有虚函数的类的文章:第 4 课 - 多态

回答by Chuck

Why not explicitly assign the class's members to the struct's when you want to pass the data to C? That way you know your code will work anywhere.

当您想将数据传递给 C 时,为什么不将类的成员显式分配给结构的成员?这样你就知道你的代码可以在任何地方工作。

回答by Mike Thompson

Classes & structs in C++ are the equivalent, except that all members of a struct are public by default (class members are private by default). This ensures that compiling legacy C code in a C++ compiler will work as expected.

C++ 中的类和结构是等价的,除了结构的所有成员默认都是公共的(类成员默认是私有的)。这确保在 C++ 编译器中编译遗留 C 代码将按预期工作。

There is nothing stopping you from using all the fancy C++ features in a struct:

没有什么可以阻止您在结构中使用所有花哨的 C++ 功能:

struct ReallyAClass
{
    ReallyAClass();
    virtual !ReallAClass();

    /// etc etc etc
};

回答by Daemin

You probably just derive the class from the struct, either publicly or privately. Then casting it would resolve correctly in the C++ code.

您可能只是从结构派生类,无论是公开的还是私有的。然后转换它会在 C++ 代码中正确解析。