1. New的本质
当使用关键字new在堆上动态创建一个对象时,它实际上做了三件事:
① 获得一块内存空间
② 调用类构造函数
③ 返回指向地址的正确指针
如果创建的是简单类型的变量,第二步就不执行了。下面我们看一段代码:
1 #include <iostream> 2 3 4 class A { 5 int m_value; 6 public: 7 A(int value) :m_value(value * value){} 8 void Func(){ 9 std::cout<< m_value; 10 } 11 }; 12 13 int main() 14 { 15 A *aPtr = new A(1); 16 delete *aPtr; 17 system("pause"); 18 return 0; 19 } |
在调用 “A *a = new A(1);” 时,其过程大致如下:
1 A *aPtr = (A*)malloc(sizeof(A)); // 分配内存区域
2 aPtr->A::A(1); // 调用对象构造函数
3 return aPtr; // 返回内存地址指针
上面三句话表面上看起来是得到了aPtr这个指向内存的指针。但是它与new自身的区别在于,当malloc失败的时候,上面的代码不会调用分配内存失败处理程序new_handler。而使用new的话就会。因此,我们要尽可能的使用new,避免一些不必要的麻烦。
下面是 “A *a = new A(1);” 的汇编码(windows 7, Visual Studio 2008):
1 A *aPtr = new A(1); 2 0116140D push 4 3 0116140F call operator new (1161190h) //使用new分配内存空间 4 01161414 add esp,4 5 01161417 mov dword ptr [ebp-0ECh],eax 6 0116141D mov dword ptr [ebp-4],0 7 01161424 cmp dword ptr [ebp-0ECh],0 8 0116142B je main+72h (1161442h) 9 0116142D push 1 10 0116142F mov ecx,dword ptr [ebp-0ECh] 11 01161435 call A::A (1161019h) //调用构造函数进行初始化 12 0116143A mov dword ptr [ebp-100h],eax 13 01161440 jmp main+7Ch (116144Ch) 14 01161442 mov dword ptr [ebp-100h],0 15 0116144C mov eax,dword ptr [ebp-100h] 16 01161452 mov dword ptr [ebp-0F8h],eax 17 01161458 mov dword ptr [ebp-4],0FFFFFFFFh 18 0116145F mov ecx,dword ptr [ebp-0F8h] 19 01161465 mov dword ptr [ebp-14h],ecx //返回指针 |