内存中 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
Structure of a C++ Object in Memory Vs a 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_struct
simmilar 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 = 8
and foo_struct.y = 9
(ie: the same values as the x,y values in the foo_class) ?
将foo_struct.x = 8
和foo_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 struct
and a C++ class
(or struct
-- same thing) will be identical, provided that the C++ class
/struct
fits 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++ 代码中正确解析。