从汇编看c++中的placement operator new
添加时间:2013-7-29 点击量:
placement operator new是重载的operator new运算符,它容许我们将对象放到一个指定的内存中。下面来看c++源码:
class X {
private:
int _x;
public:
X(int xx = 0) : _x(xx) {}
~X() {}
void operator new(size_t n, void location) {
return location;
}
};
int main() {
int i;
X xp = new (&i) X;//placement operator new的语法
};
下面是main函数里面的汇编码:
int i;
14: X xp = new (&i) X;
013913AE lea eax,[i] ;将i的地址给存放器eax
013913B1 push eax ;压栈eax,作为参数传递给operator new,即传递参数loc
013913B2 push 4 ;压栈内存大小4,即传递参数size_t 由编译器算出
013913B4 call X::operator new (13910FAh) ;调用operator new
013913B9 add esp,8 ;栈顶指针-8,开释调用operator new而传参时分派的栈空间
013913BC mov dword ptr [ebp-0E0h],eax ;eax保存operator new的返回值,即内存空间的首地址
;这里是变量i的地址 ,将此地址存入ebp-0E0h所代表的内存
013913C2 cmp dword ptr [ebp-0E0h],0 ;将ebp-0E0h内存里面的值与0做斗劲,断定是否为空指针
013913C9 je main+50h (13913E0h) ;若是为空,就跳转到地址13913E0h处履行,不然,次序履行
;这里次序履行
013913CB push 0 ;压入参数0,为调用机关函数传递参数
013913CD mov ecx,dword ptr [ebp-0E0h] ;将 ebp-0E0h内存中的值(变量i的地址)给存放器ecx
;作为隐含参数(即this指针)传递给机关函数
013913D3 call X::X (1391041h);调用机关函数
013913D8 mov dword ptr [ebp-0E8h],eax ;存放器eax存有对象首地址(即变量i的地址),将eax的值给ebp-0E8h所代表的内存
013913DE jmp main+5Ah (13913EAh) ;跳转到地址13913EAh处履行
013913E0 mov dword ptr [ebp-0E8h],0 ;这一条指令是013913C2 处断定失败后将要履行的指令
;将0给ebp-0E8h所代表的内存
013913EA mov ecx,dword ptr [ebp-0E8h] ;将ebp-0E8h内存的值给存放器ecx
013913F0 mov dword ptr [xp],ecx ;ecx的值(对象首地址)给指针变量xp
15: };
从汇编码可以看到,起首调用重载之后的placement operator new运算符,它仅仅返回的是变量i的地址。接下来,编译器将这个地址作为所要机关对象的首地址,作为this指针传给了机关函数,进行机关函数的调用。最后,将对象首地址(也就是变量i的地址)给了指针变量xp,从而在变量i处的内存中机关了一个对象。
须要重视的是若是类X所占用的内存比一个int i大,那么,在这种景象下机关的时辰,将引起法度溃散。
placement operator new是重载的operator new运算符,它容许我们将对象放到一个指定的内存中。下面来看c++源码:
class X {
private:
int _x;
public:
X(int xx = 0) : _x(xx) {}
~X() {}
void operator new(size_t n, void location) {
return location;
}
};
int main() {
int i;
X xp = new (&i) X;//placement operator new的语法
};
下面是main函数里面的汇编码:
int i;
14: X xp = new (&i) X;
013913AE lea eax,[i] ;将i的地址给存放器eax
013913B1 push eax ;压栈eax,作为参数传递给operator new,即传递参数loc
013913B2 push 4 ;压栈内存大小4,即传递参数size_t 由编译器算出
013913B4 call X::operator new (13910FAh) ;调用operator new
013913B9 add esp,8 ;栈顶指针-8,开释调用operator new而传参时分派的栈空间
013913BC mov dword ptr [ebp-0E0h],eax ;eax保存operator new的返回值,即内存空间的首地址
;这里是变量i的地址 ,将此地址存入ebp-0E0h所代表的内存
013913C2 cmp dword ptr [ebp-0E0h],0 ;将ebp-0E0h内存里面的值与0做斗劲,断定是否为空指针
013913C9 je main+50h (13913E0h) ;若是为空,就跳转到地址13913E0h处履行,不然,次序履行
;这里次序履行
013913CB push 0 ;压入参数0,为调用机关函数传递参数
013913CD mov ecx,dword ptr [ebp-0E0h] ;将 ebp-0E0h内存中的值(变量i的地址)给存放器ecx
;作为隐含参数(即this指针)传递给机关函数
013913D3 call X::X (1391041h);调用机关函数
013913D8 mov dword ptr [ebp-0E8h],eax ;存放器eax存有对象首地址(即变量i的地址),将eax的值给ebp-0E8h所代表的内存
013913DE jmp main+5Ah (13913EAh) ;跳转到地址13913EAh处履行
013913E0 mov dword ptr [ebp-0E8h],0 ;这一条指令是013913C2 处断定失败后将要履行的指令
;将0给ebp-0E8h所代表的内存
013913EA mov ecx,dword ptr [ebp-0E8h] ;将ebp-0E8h内存的值给存放器ecx
013913F0 mov dword ptr [xp],ecx ;ecx的值(对象首地址)给指针变量xp
15: };
从汇编码可以看到,起首调用重载之后的placement operator new运算符,它仅仅返回的是变量i的地址。接下来,编译器将这个地址作为所要机关对象的首地址,作为this指针传给了机关函数,进行机关函数的调用。最后,将对象首地址(也就是变量i的地址)给了指针变量xp,从而在变量i处的内存中机关了一个对象。
须要重视的是若是类X所占用的内存比一个int i大,那么,在这种景象下机关的时辰,将引起法度溃散。