【问题标题】:behaviour of sizeof in c++c++中sizeof的行为
【发布时间】:2018-02-26 06:23:56
【问题描述】:

当我在 c++ 中做 sizeof 时,我一定会得到“整个对象”吗?我问是因为我即将使用 memcpy 将对象复制到内存的其他区域(可能从一开始就是一个愚蠢的想法,对吧?)。

我担心的是我可能无法获得整个对象,而只能获得属于它现在被投射到的类的部分。这有什么意义还是我很困惑?

编辑示例

 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”类的“整体”对象?

【问题讨论】:

  • 您是否尝试打印这些尺寸?还是使用调试器?当然sizeof(b)sizeof(a 大(可能大4 个字节)
  • 可能是因为 填充。查看非常相关的(如果不重复?)Why isn't sizeof for a struct equal to the sum of sizeof of each member?
  • 是的,在 C++ 中使用 memcpy 通常是一个非常糟糕的主意,除了普通的旧数据 (POD) 结构。
  • 不考虑“铸造”而是考虑对象的实际类型可能会有所帮助。 a 的类型为 Ab 的类型为 BA 对象是如何创建的并不重要,它的sizeof 是一个常量。
  • memcpy 如果对象是 TriviallyCopyable(例如标量、数组、C 兼容结构),则可以。对于不是 TriviallyCopyable 的对象,除非您确切知道自己在做什么,否则您很有可能会遇到未定义的行为。

标签: c++ oop memory memcpy


【解决方案1】:

sizeof 将始终返回对象的 static 大小。请注意,在您的示例中,它将与真实的对象大小一致,因为没有多态性;当你这样做时

A a = B();

a is 类型为A - 你刚刚用新的B 对象初始化了一个新的A 对象,这导致了切片(a 被初始化为B()A 共有的字段)。

一个更好的例子是:

B b;
A *a = &b;

在这种情况下,*a 确实是动态类型B,但sizeof(*a) 仍将返回sizeof(A),而不是sizeof(B)

有几种方法可以获取对象的动态大小:

  • 在施工时将其保存到字段中;
  • 理论上,您可以定义一个虚拟方法来执行return sizeof(*this); 并在所有派生类中重新定义它。

话虽如此,这最后一种方法不会特别有用,因为对诸如多态类之类的非平凡类型执行memcpy 是未定义的行为(因此,即使是第一种方法也是如此,正如我想象的那样会想用多态类型来做到这一点)。


解决复制多态类问题的常用方法是接受这样一个事实,即它们必须存在于堆中并定义 clone() 方法来执行 virtual A * clone() {return new B(*this);}(其中 B 是派生类)每个派生类,并在需要副本时调用clone()

请注意,您可以使用更微妙的技巧;一旦我有一个类层次结构,它有一个虚拟方法分派到每个派生类的位置new,一个用于析构函数,但你真的必须知道你在做什么(在我的例子中,我通过@987654343调用它们@ 包含每个派生类的实例,因此大小和对齐不是问题)。

【讨论】:

  • 好吧,但是如果我在 A* a = &b; 之后执行 dynamic_cast(a)然后我会得到a的B方面吗?
  • 然后你会得到sizeof(B*);如果你做sizeof(*dynamic_cast&lt;B*&gt;(a)),你会得到sizeof(B),无论演员阵容返回。即使您检查它可能返回的内容,它也会为从B(不仅仅是B)派生的任何类返回非NULL 值,因此实际大小可能更大。要获得精确的类型匹配,您必须使用typeid,但由于所有typeiddynamic_cast 和虚方法都需要多态类,因此您不能将它们中的任何一个与memcpy 一起使用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-28
  • 2012-08-27
  • 2014-12-26
  • 2011-01-13
  • 1970-01-01
  • 1970-01-01
  • 2019-11-23
相关资源
最近更新 更多