C++ 中 sizeof 的行为
behaviour of sizeof in c++
当我用c++做sizeof的时候,一定能得到"whole object"吗?我问是因为我将要使用 memcpy 将对象复制到内存的其他区域(从一开始可能是一个愚蠢的想法,对吧?)。
我担心的是我可能无法获得整个对象,而只能获得属于 class 的部分。它有任何意义还是我感到困惑?
编辑 示例
class A{ public: int a = 123; };
class B: public A{ public: int b = 321; };
class C : public B{ public: int c = 333; };
C c_ = C();
B b_ = C();
A a_ = C();
std::cout << sizeof(a_) << " , " << sizeof(b_) << " , " << sizeof(c_) << std::endl;
好像给我4,8,12.
我想我需要进行动态转换才能弄清楚如何获取我在每种情况下构造为 "C" class 的 "whole" 对象?
sizeof
将始终 return 您对象的 static 大小。请注意,在您的示例中,它将与真实对象大小一致,因为没有多态性;当你这样做时
A a = B();
a
是 类型 A
- 你刚好用新的 B
初始化了一个新的 A
对象对象,这会导致切片(a
使用 B()
的字段初始化,这些字段与 A
相同)。
一个更好的例子是:
B b;
A *a = &b;
在这种情况下,*a
确实是动态类型B
,但sizeof(*a)
仍然是return sizeof(A)
,而不是sizeof(B)
.
有几种方法可以获取对象的动态大小:
- 在构建时将其保存到字段中;
- 理论上,您可以定义一个执行
return sizeof(*this);
的虚方法,并在所有派生的 class 中重新定义它。
也就是说,最后一个方法不会特别有用,因为 non-trivial 类型的 memcpy
,例如多态 classes 是未定义的行为(因此即使第一种方法也是如此,因为我想你会想要用多态类型来做到这一点)。
复制多态 classes 问题的常见方法是接受它们必须存在于堆中的事实,并定义 clone()
执行 virtual A * clone() {return new B(*this);}
的方法(其中 B
是派生的 class)在每个派生的 class 中,并在需要副本时调用 clone()
。
请注意,您可以使用更微妙的技巧;一旦我有一个 class 层次结构,它有一个虚拟方法调度到放置 new
每个派生 class 和一个用于析构函数,但你真的必须知道你在做什么(在我的情况是通过 union
调用它们,其中包含每个派生 class 的实例,因此大小和对齐不是问题)。
当我用c++做sizeof的时候,一定能得到"whole object"吗?我问是因为我将要使用 memcpy 将对象复制到内存的其他区域(从一开始可能是一个愚蠢的想法,对吧?)。
我担心的是我可能无法获得整个对象,而只能获得属于 class 的部分。它有任何意义还是我感到困惑?
编辑 示例
class A{ public: int a = 123; };
class B: public A{ public: int b = 321; };
class C : public B{ public: int c = 333; };
C c_ = C();
B b_ = C();
A a_ = C();
std::cout << sizeof(a_) << " , " << sizeof(b_) << " , " << sizeof(c_) << std::endl;
好像给我4,8,12.
我想我需要进行动态转换才能弄清楚如何获取我在每种情况下构造为 "C" class 的 "whole" 对象?
sizeof
将始终 return 您对象的 static 大小。请注意,在您的示例中,它将与真实对象大小一致,因为没有多态性;当你这样做时
A a = B();
a
是 类型 A
- 你刚好用新的 B
初始化了一个新的 A
对象对象,这会导致切片(a
使用 B()
的字段初始化,这些字段与 A
相同)。
一个更好的例子是:
B b;
A *a = &b;
在这种情况下,*a
确实是动态类型B
,但sizeof(*a)
仍然是return sizeof(A)
,而不是sizeof(B)
.
有几种方法可以获取对象的动态大小:
- 在构建时将其保存到字段中;
- 理论上,您可以定义一个执行
return sizeof(*this);
的虚方法,并在所有派生的 class 中重新定义它。
也就是说,最后一个方法不会特别有用,因为 non-trivial 类型的 memcpy
,例如多态 classes 是未定义的行为(因此即使第一种方法也是如此,因为我想你会想要用多态类型来做到这一点)。
复制多态 classes 问题的常见方法是接受它们必须存在于堆中的事实,并定义 clone()
执行 virtual A * clone() {return new B(*this);}
的方法(其中 B
是派生的 class)在每个派生的 class 中,并在需要副本时调用 clone()
。
请注意,您可以使用更微妙的技巧;一旦我有一个 class 层次结构,它有一个虚拟方法调度到放置 new
每个派生 class 和一个用于析构函数,但你真的必须知道你在做什么(在我的情况是通过 union
调用它们,其中包含每个派生 class 的实例,因此大小和对齐不是问题)。