用汇编的眼光看C++(之class构造、析构)09
2012-01-17 09:58
204 查看
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
前面我们讨论基本上都是C语言的内容,还没有真正触及到C++的相关知识。从这篇博客之后,我们将会更多触及类的内容。类的属性很多,今天我们讨论主要就是构造函数、析构函数。
(1)如果没有构造函数、析构函数呢?
[cpp] view plaincopy
class apple
{
public:
void print() const {return;}
};
虽然这个类没有什么意义,但是如果用sizeof计算一下大小的话,我们发现它还是占了一个字节。那么如果有一个apple的变量呢?为了让apple的变量有意义,我们尝试做一个改变:
[cpp] view plaincopy
66: apple a;
67: a.print();
00401248 lea ecx,[ebp-4]
0040124B call @ILT+0(apple::print) (00401005)
68: return;
69: }
我们看到,堆栈分配了四个字节空间给a,就是ebp下面的一个字节。
(2) 析构函数什么时候调用?
[cpp] view plaincopy
class apple
{
public:
apple() {printf("apple()!\n");}
~apple() {printf("~apple()!\n");}
void print() const {return;}
};
如果调用呢,我们可以做一个测试环境,如下所示:
[cpp] view plaincopy
68: apple a;
0040126D lea ecx,[ebp-10h]
00401270 call @ILT+65(apple::apple) (00401046)
00401275 mov dword ptr [ebp-4],0
69: {
70: apple b;
0040127C lea ecx,
0040127F call @ILT+65(apple::apple) (00401046)
71: }
00401284 lea ecx,[b]
00401287 call @ILT+0(apple::~apple) (00401005)
0040128C mov dword ptr [ebp-4],0FFFFFFFFh
72: }
00401293 lea ecx,[ebp-10h]
00401296 call @ILT+0(apple::~apple) (00401005)
0040129B mov ecx,dword ptr [ebp-0Ch]
0040129E mov dword ptr fs:[0],ecx
我们看到,只要出了作用域,析构函数就会自动会被调用。
[b](3)如果是new调用类,析构函数会自动调用吗?
不会。
(4)构造函数、析构函数的本质?
我们知道在函数中的临时变量在堆栈里面应用的时候都需要初始化处理的,在堆栈返回的时候会被自动收回。那么构造函数和析构函数?其实是一样的,在函数调 用的时候,堆栈也会为这样一个类准备大小合适的堆栈,然后调用构造函数对这样的一片内存进行初始化处理,在函数return的时候,调用另外一个函数对可 能涉及到的资源进行一次清理。这里指的资源不是指内存空间,而是指广义意义上的系统资源、比如说IO、socket、锁、画笔、对话框句柄等等。所以,通 常而言,如果你在析构函数里面没有及时对资源进行分配,那么就会造成资源的泄露。这一切只有等到程序结束的时候才会重新回到系统的手中,不过如果一个程序 占有太多的资源,那么势必会对别的程序造成影响。
前面我们讨论基本上都是C语言的内容,还没有真正触及到C++的相关知识。从这篇博客之后,我们将会更多触及类的内容。类的属性很多,今天我们讨论主要就是构造函数、析构函数。
(1)如果没有构造函数、析构函数呢?
[cpp] view plaincopy
class apple
{
public:
void print() const {return;}
};
虽然这个类没有什么意义,但是如果用sizeof计算一下大小的话,我们发现它还是占了一个字节。那么如果有一个apple的变量呢?为了让apple的变量有意义,我们尝试做一个改变:
[cpp] view plaincopy
66: apple a;
67: a.print();
00401248 lea ecx,[ebp-4]
0040124B call @ILT+0(apple::print) (00401005)
68: return;
69: }
我们看到,堆栈分配了四个字节空间给a,就是ebp下面的一个字节。
(2) 析构函数什么时候调用?
[cpp] view plaincopy
class apple
{
public:
apple() {printf("apple()!\n");}
~apple() {printf("~apple()!\n");}
void print() const {return;}
};
如果调用呢,我们可以做一个测试环境,如下所示:
[cpp] view plaincopy
68: apple a;
0040126D lea ecx,[ebp-10h]
00401270 call @ILT+65(apple::apple) (00401046)
00401275 mov dword ptr [ebp-4],0
69: {
70: apple b;
0040127C lea ecx,
0040127F call @ILT+65(apple::apple) (00401046)
71: }
00401284 lea ecx,[b]
00401287 call @ILT+0(apple::~apple) (00401005)
0040128C mov dword ptr [ebp-4],0FFFFFFFFh
72: }
00401293 lea ecx,[ebp-10h]
00401296 call @ILT+0(apple::~apple) (00401005)
0040129B mov ecx,dword ptr [ebp-0Ch]
0040129E mov dword ptr fs:[0],ecx
我们看到,只要出了作用域,析构函数就会自动会被调用。
[b](3)如果是new调用类,析构函数会自动调用吗?
不会。
(4)构造函数、析构函数的本质?
我们知道在函数中的临时变量在堆栈里面应用的时候都需要初始化处理的,在堆栈返回的时候会被自动收回。那么构造函数和析构函数?其实是一样的,在函数调 用的时候,堆栈也会为这样一个类准备大小合适的堆栈,然后调用构造函数对这样的一片内存进行初始化处理,在函数return的时候,调用另外一个函数对可 能涉及到的资源进行一次清理。这里指的资源不是指内存空间,而是指广义意义上的系统资源、比如说IO、socket、锁、画笔、对话框句柄等等。所以,通 常而言,如果你在析构函数里面没有及时对资源进行分配,那么就会造成资源的泄露。这一切只有等到程序结束的时候才会重新回到系统的手中,不过如果一个程序 占有太多的资源,那么势必会对别的程序造成影响。
相关文章推荐
- 用汇编的眼光看C++(之class构造、析构)
- 用汇编的眼光看C++(之class构造、析构)
- 用汇编的眼光看C++(之class构造、析构) ,(之拷贝、赋值函数)
- 用汇编的眼光看C++(之class构造、析构)
- 用汇编的眼光看C++(之class构造、析构)
- 用汇编的眼光看C++(之class构造、析构)
- Effective C++ 条款09 绝不在构造和析构过程中调用virtual函数
- C++反汇编第二讲,不同作用域下的构造和析构的识别
- C++构造与析构(17) - virtual拷贝构造函数
- 【C++学习历程3】对象的构造和析构
- c++构造和析构能不能抛异常的总结!
- C++构造和析构定义的经验总结
- [C++]搞清楚类中构造与析构的顺序
- 用汇编的眼光看C++(开篇)
- 用汇编的眼光看C++(之拷贝、赋值函数)
- Effective C++第二章-构造,析构,赋值 -2
- 从汇编的眼光看C++(之指针拷贝)
- 用汇编的眼光看C++(之循环流程)
- C++学习笔记:3.3.4 继承和组合混搭情况下,构造和析构调用顺序
- 用汇编的眼光看C++(之虚函数)