Pra*_*rav 5 c++ pointers reference
考虑一个小单元测试用例
struct A
{
virtual void func(){}
A& foo()
{
A *obj = reinterpret_cast<A*>(0xdeadbeef);
return *obj; //1
}
};
int main()
{
A obj = obj.foo();
}
Run Code Online (Sandbox Code Playgroud)
在线1是它实现定义/未指定,因为我们通过引用返回时不会发生deference,如果没有对指向的对象进行显式访问,程序不会崩溃?
我与我的一位同事争论过,他提到在大多数情况下编译器会优化取消引用,obj因为我们通过引用返回它并且这段代码不会崩溃?
谢谢
我在MS VC8.0中反汇编了代码,发现更有趣的事情:
006D48D6 mov dword ptr [ebp-8],ecx
A *obj = reinterpret_cast<A*>(0xdeadbeef);
006D48D9 mov dword ptr [obj],0DEADBEEFh
return *obj; //1
006D48E0 mov eax,dword ptr [obj] //2
}
006D48E3 mov esp,ebp
006D48E5 pop ebp
006D48E6 ret
Run Code Online (Sandbox Code Playgroud)
//2表示将obj的地址作为返回值放入eax寄存器中。
006D39FC lea ecx,[ebp-190h]
006D3A02 call A::foo (6A8C12h)
006D3A07 push eax //3
006D3A08 lea ecx,[ebp-190h]
006D3A0E call A::A (6B89BEh)
Run Code Online (Sandbox Code Playgroud)
eax 是 0xdeadbeef,并像临时局部变量一样压入堆栈。然后我们调用复制构造函数(这很简单)。所有这些操作都只是传递地址(这是非法的,但程序不关心)。因为 A 结构没有任何绑定到特定对象的成员,如果没有,程序将不会尝试通过解引用来查找特定对象不需要。所以这颗炸弹还没有发射。
A *obj = reinterpret_cast<A*>(0xdeadbeef);
A tmp ;
temp = *obj;
Run Code Online (Sandbox Code Playgroud)
即使这样也没关系,因为operator=也是按引用传递,实际上传递的是地址。如果添加成员变量,它将失败,因为它将尝试查找并复制该成员。