【问题标题】:Is an object's 'this' pointer equal to a pointer to its (single) base class?对象的“this”指针是否等于指向其(单个)基类的指针?
【发布时间】:2017-12-13 06:33:41
【问题描述】:

鉴于以下情况:

class B
{
  // impl here, can be anything valid for a class
};

class D : public B
{
};

void main()
{
  D real;
  D * pd = ℜ
  B * pb = ℜ

  // assert(pb == pd);
  // Edit: I meant:
  assert((void *)pb == (void *)pd);
}

pb == pd 是否由 c++ 标准保证?如果不是,在实践中是否总是如此? (这是假设BD 的唯一基类)

【问题讨论】:

  • 不,不是。考虑一个将基类成员放在末尾而不是开头的实现。合法的。奇怪,但合法。
  • 同时考虑多重继承。
  • 或者不是 MI,但如果它是虚拟继承(这种情况下很可能将基础放置在末尾),但是对于单个非虚拟基础,断言很可能是真的.我很确定只有在 std::is_standard_layout 为真时才能保证。
  • 是的,保证pb == pd。如果要保证(void*)pb == (void*)pd,那么不行,这个绝对不能保证。
  • 是的,阅读整个标准。在任何地方都找不到保证。不了解“始终在实践中”,我无法在所有情况下尝试所有编译器。

标签: c++ inheritance language-lawyer memory-layout


【解决方案1】:

如果不是,在实践中是否总是如此? (这是假设BD 的唯一基类)

不。即使这个假设也无济于事。考虑一下这个有效的修改:

class D : public B
{
  virtual ~D() = default;
};

D 现在是多态的,而B 不是。实际上,这意味着为动态调度添加了一个指针。普遍添加在对象的开头。所以现在B 子对象处于偏移位置,尽管它是唯一的基础。

值得注意的是,正如@melpomene 所指出的,您的测试仍然会通过。由于D* 可以隐式转换为B*,所以当您assert(pb == pd); 时,编译器已经为您进行了调整。我的观点是,你不能指望重新解释演员表(我知道你问的是地址的平面重新解释)是正确的。

【讨论】:

  • pb == pdpd 隐式转换为B *,从而补偿偏移量。
  • @melpomene - 是的。但我收集了关于平面重新解释演员表的 OP 奇观。但是,我可能误解了。
  • 好吧,OP 询问“c++ 标准是否保证pb == pd” 而OP 的代码可以保证assert(pb == pd),所以看起来确实是字面意思。
  • @melpomene - 添加了这一点。我认为 OP 只是表达得很糟糕。如果他们不这样做,这应该被否决:)
  • 你是对的,我的意思是((void *)pb == (void *)pd)(将更新问题)。但是您的反例不合适,因为我指定 D 为空。
猜你喜欢
  • 1970-01-01
  • 2019-12-28
  • 2023-02-09
  • 2011-11-12
  • 1970-01-01
  • 2010-09-22
  • 2021-05-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多