placement new 和普通的 new 运算符的一个关键区别就在于内存分配和对象构造是分开的,这也是为什么你需要分别处理内存释放和对象析构。
普通的 new 和 delete
- 普通的
new:在普通的new操作中,内存分配和对象构造是同时进行的。当你写T* obj = new T(args...);时,系统会首先为对象分配足够的内存,然后调用对象的构造函数在这块内存上构造对象。 - 普通的
delete:当你调用delete obj;时,系统会自动做两件事:首先调用对象的析构函数,然后释放内存。这两步是紧密结合的,确保了对象的生命周期和内存管理都是自动化的。
placement new
-
placement new:在placement new的操作中,内存分配和对象构造是分开的。你手动分配一块内存,然后使用placement new在这块内存上构造对象。这种分离给你带来了更大的灵活性,但也意味着你必须手动管理对象的生命周期和内存的释放。 -
void*指针: placement new需要void*的指针来指明构造对象的地址位置。
-
例如:
void* memory = operator new(sizeof(MyClass)); // 手动分配内存 注意 operator new和new的区别 //void* memory = malloc(sizeof(MyClass)); MyClass* obj = new(memory) MyClass(42); // 在分配的内存上构造对象这里
memory是你手动分配的内存,而对象obj是在这块内存上构造的。 -
手动析构和释放内存:
- 析构对象:你需要在合适的时机手动调用析构函数来销毁对象。例如,
obj->~MyClass();会调用对象的析构函数,但这不会释放内存。 - 释放内存:你还需要手动释放之前分配的内存。例如,
operator delete(memory);会释放内存。这与普通的delete不同,因为delete会自动调用析构函数和释放内存,而在使用placement new时,这两个步骤是分开的。
- 析构对象:你需要在合适的时机手动调用析构函数来销毁对象。例如,
总结
因为 placement new 分离了内存分配和对象构造,你必须手动管理这两个过程。构造对象后,必须手动调用析构函数来销毁对象,然后手动释放内存。普通的 new 和 delete 是一气呵成的,placement new 则要求你分开进行这两步操作。

被折叠的 条评论
为什么被折叠?



