从汇编看c++中的placement operator new
placement operator new是重载的operator new运算符,它允许我们将对象放到一个指定的内存中。下面来看c++源码:
class X {
private:
int _x;
public:
X(int xx = ) : _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;
: X* xp = new (&i) X;
013913AE lea eax,[i] ;将i的地址给寄存器eax
013913B1 push eax ;压栈eax,作为参数传递给operator new,即传递参数loc
013913B2 push ;压栈内存大小4,即传递参数size_t 由编译器算出
013913B4 call X::operator new (13910FAh) ;调用operator new
013913B9 add esp, ;栈顶指针-8,释放调用operator new而传参时分配的栈空间
013913BC mov dword ptr [ebp-0E0h],eax ;eax保存operator new的返回值,即内存空间的首地址
;这里是变量i的地址 ,将此地址存入ebp-0E0h所代表的内存
013913C2 cmp dword ptr [ebp-0E0h], ;将ebp-0E0h内存里面的值与0做比较,判断是否为空指针
013913C9 je main+50h (13913E0h) ;如果为空,就跳转到地址13913E0h处执行,否则,顺序执行
;这里顺序执行
013913CB push ;压入参数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], ;这一条指令是013913C2 处判断失败后将要执行的指令
;将0给ebp-0E8h所代表的内存
013913EA mov ecx,dword ptr [ebp-0E8h] ;将ebp-0E8h内存的值给寄存器ecx
013913F0 mov dword ptr [xp],ecx ;ecx的值(对象首地址)给指针变量xp
: };
从汇编码可以看到,首先调用重载之后的placement operator new运算符,它仅仅返回的是变量i的地址。接下来,编译器将这个地址作为所要构造对象的首地址,作为this指针传给了构造函数,进行构造函数的调用。最后,将对象首地址(也就是变量i的地址)给了指针变量xp,从而在变量i处的内存中构造了一个对象。
需要注意的是如果类X所占用的内存比一个int i大,那么,在这种情况下构造的时候,将引起程序崩溃。
从汇编看c++中的placement operator new的更多相关文章
- 从汇编看c++中指向成员变量的指针(二)
在从汇编看c++中指向成员变量的指针(一)中讨论的情形没有虚拟继承,下面来看看,当加入了虚拟继承的时候,指向成员变量的指针有什么变化. 下面是c++源码: #include <iostream& ...
- 从汇编看c++中成员函数指针(一)
下面先来看c++的源码: #include <cstdio> using namespace std; class X { public: int get1() { ; } virtual ...
- 从汇编看c++中指向成员变量的指针(一)
在c++中,指向类成员变量的指针存储的并不是该成员变量所在内存的地址,而仅仅是该成员变量在该类对象中相对于对象首地址的偏移量.因此,它必须绑定到某一个对象或者对象指针上面,这里的对象和对象指针,就相当 ...
- 从汇编看c++中的虚拟继承及内存布局(二)
下面是c++源码: class Top {//虚基类 public: int i; Top(int ii) { i = ii; } virtual int getTop() { cout <&l ...
- 从汇编看c++中的多态
http://www.cnblogs.com/chaoguo1234/archive/2013/05/19/3079078.html 在c++中,当一个类含有虚函数的时候,类就具有了多态性.构造函数的 ...
- 从汇编看c++中临时对象的析构时机
http://www.cnblogs.com/chaoguo1234/archive/2013/05/12/3074425.html c++中,临时对象一旦不需要,就会调用析构函数,释放其占有的资源: ...
- 从汇编看c++中含有虚基类对象的析构
c++中,当继承结构中含有虚基类时,在构造对象时编译器会通过将一个标志位置1(表示调用虚基类构造函数),或者置0(表示不调用虚基类构造函数)来防止重复构造虚基类子对象.如下图菱形结构所示: 当构造类B ...
- 从汇编看c++中全局对象和全局变量
先来看c++源码: #include <iostream> using namespace std; class X { public: int i; public: X() : i(ii ...
- 从汇编看c++成员函数指针(三)
前面的从汇编看c++中成员函数指针(一)和从汇编看c++成员函数指针(二)讨论的要么是单一类,要么是普通的多重继承,没有讨论虚拟继承,下面就来看一看,当引入虚拟继承之后,成员函数指针会有什么变化. 下 ...
随机推荐
- 如何在WebSocket类中访问Session
我最近正在做一个基于websocket的webQQ,最后代码会开源带github上,所以过程中我就不贴所有的代码啦~就贴问题的关键. 我在WebSocket里发消息的时候需要用到session,因为在 ...
- 《APUE》-第五章标准IO库
大多数UNIX应用程序都使用I/O库,本章说明了该库所包含的所有函数,以及某些实现细节和效率方面的考虑.同时需要重点关注标准I/O使用了缓冲的技术,但同时也是因为它的出现,产生了很多细节上的问题. 流 ...
- 自己动手写谷歌API翻译接口
可以看到,利用GET请求方式,带入某些参数,就会返回一个json数组,QueryString参数如下: 同样的,我们只需要传入这三个参数,就可以获得我们想要的翻译内容,公开方法,代码如下. ...
- Keil C51里关于堆栈指针的处理
Keil C是非常优秀的C51编译器,可能是最好的C51编译器,提供各种优化模式,对变量的优化和地址安排做得非常好.这是用C语言写代码的好处之一,如果用汇编写,得费一大番功夫给各个变量安排内存物理地址 ...
- keil c51中C程序的启动过程
汇编是从org 0000h开始启动,那么keil c51是如何启动main()函数的?keil c51有一个启动程序startup.a51,它总是和c程序一起编译和链接.下面看看它和main()函数是 ...
- 模拟IIC总线汇编程序软件包
一.概述 为了非常方便地对 I2C 从器件进行快速的.正确的读写操作,我们为此而设计出虚拟 I2C 总线操作平台软件包.本软件包是主方式下的虚拟 I2C 总线软件包,只要用户给子程序提供几个主要的参数 ...
- PowerShell3.0中,所有的命令
Get-Command * >> cmd.txt CommandType Name ModuleName ----------- ---- ---------- Alias % -> ...
- linux find详解
find是最常见和最强大的查找命令,你可以用它找到任何你想找的文件. find的使用格式如下: $ find <指定目录> <指定条件> <指定动作> - < ...
- hmac_sha1 签名
use URI::Escape qw(uri_unescape); use MIME::Base64; use Digest::HMAC_SHA1; $str=Digest::HMAC_SHA1::h ...
- REST API初识及设计
网络应用程序,分为前端和后端两个部分.当前的发展趋势,就是前端设备层出不穷(手机.平板.桌面电脑.其他专用设备......). 因此,必须有一种统一的机制,方便不同的前端设备与后端进行通信.这导致AP ...