在深入学习C++的过程中遇到3个new和delete让我十分迷惑,经过学习,有了点初步理解的感觉。总结如下
C++中,内存分配和对象构造紧密纠缠,就像对象析构和内存回收一样。使用new 表达式的时候,分配内存,并在该内存中构造一个对象,使用delete的时候,调用析构函数撤销对象,并将对象所用内存返还给系统。
C++提供了一下两种方法来分配和释放未构造的原始内存:
1)allocator类的allocate 和 deallocate成员函数
2)标准库中的 operator new 和 operator delete。
C++还提供了在原始未构造的内存中构造和析构对象:
1)allocator类的construct 和 destroy成员函数
2)定位new表达式,接收指向未构造的内存的指针,并在该空间中初始化一个对象或数组。
3)直接调用对象的析构函数撤销对象。
1. new 表达式 和 delete 表达式
就是我们最常用的。比如:A* a = new A(); delete a; 这中用法很常见。
但是很少人了解里面的机制。
其实,当使用new的时候,发生了3个步骤:
1) 调用 operator new 的标准库函数,分配足够大的原始未类型化的内存。(没有进行构造)
2) 运行该类型的构造函数
3) 返回指向新分配并构造的对象指针。
delete是发生了2步:调用析构函数,释放内存空间。
2. operator new 和 operator delete
operator new 和 operator delete的设计意图是供表达式new 和 delete 使用。但是他们通常是标准库中可调用的函数。可以使用他们获得 未构造 内存空间。他们有点类似与allocator类的 allocate 和 deallocate成员函数。
operator new 和 operator delete有两个重载版本:
void *operator new(size_t);
void *operator new[](size_t);
void *operator delete(void*);
void *operator delete[](void*);
他们在void*指针,而不是类型化指针上操作。并且只是分配内存空间,并不初始化。
3 placement new (翻译成 定位new表达式)
定位new表达式在已经分配了的内存中初始化了一个对象。它并不分配内存。相反,它接收指向已经分配的但是没有构造的内存指针,并在该内存中初始化一个对象。 它能使我们在特定的,预分配的内存地址构造一个对象。
定位new表达式是:
new (place_address) type
new (place_address) type (initializer-list)
其中place_address必须是个指针,nitializer-list是初始化列表。
可以使用定位new表达式代替allocator 里的 construct函数。定位new表达式初始化一个对象的时候,可以使用任何构造函数(constructor只能使用 拷贝构造函数),并且直接建立对象。
例如:
new(sp) string(b,e);
alloc.construct(sp+1,string(b,e));
相对于 定位new表达式 析构操作的是 显示的调用析构函数。显示调用析构函数只是清除对象本身,但是并没有释放对象所占用的内存。