1

我有一个函数并调用它:

Class1& Class2::get()
{
   return *m_ptr;
}

Class1& c = m_class2->get();

m_ptr 是一个自定义智能指针,我可以在调试器中看到 m_ptr.m_p 为 0,我也可以在其运算符 T* 内部看到它确实返回 0。但是 c (&c) 的地址不是 NULL,它是 0x30!我在反汇编中看到的:

13059       return *m_ptr;
eaabbc7e:   mov 0x8(%ebp),%eax
eaabbc81:   add $0xb4,%eax
eaabbc86:   mov %eax,(%esp)
eaabbc89:   call 0xea9ce4c0  <operator T*>
eaabbc8e:   add $0x30,%eax
13060     }

就在添加 $0x30,%eax 行之前,我可以看到 %eax 为 0,即运算符正确返回 NULL。

为什么要添加 0x30 的行在这里???

4

1 回答 1

4

尽管没有足够的信息来回答,但您的评论暗示Class2涉及多重继承,我会冒险猜测模板参数T是派生类,而不是Class2其本身。

所以operator T*返回一个指向这个派生类的指针。为了将其取消引用为 give Class2&,必须将其转换为Class2*,这可能涉及向指针添加偏移量,具体取决于编译器如何布置对象中的基类子对象。

显然,这仅在指针不为空时才有效;这就是为什么即使只使用结果来初始化引用,也决不能取消引用空指针的原因之一。

如果函数返回Class2*,那么您将按预期得到一个空指针;需要该转换才能将 null 转换为 null。在您的情况下,由于您在这种情况下通过取消引用指针来调用未定义的行为,因此编译器无需在执行转换之前检查 null 。

于 2012-04-19T10:16:33.480 回答