面试题答案
一键面试1. placement new原理
placement new
是C++的一种特殊的 new
表达式,它允许在已分配的内存上构造对象。其原理是,普通的 new
操作符会在堆上分配内存并调用对象的构造函数。而 placement new
只调用对象的构造函数,它假定调用者已经为对象分配好了合适大小的内存空间。其语法为 new (place_address) type
或 new (place_address) type (initializers)
,其中 place_address
是一个指向已分配内存的指针。
2. 用途
- 在特定内存位置构造对象:当需要在特定的内存地址(例如共享内存、内存池等)上构造对象时使用。
- 避免频繁内存分配:在一些对性能敏感且需要频繁创建和销毁对象的场景下,可预先分配大块内存,然后使用
placement new
在这些内存上创建对象,减少堆内存分配的开销。
3. 实际开发场景
场景一:内存池
- 使用方法:
- 首先分配一块大内存作为内存池,例如
char* buffer = new char[sizeof(MyClass)];
- 使用
placement new
在内存池上构造对象:MyClass* obj = new (buffer) MyClass();
- 首先分配一块大内存作为内存池,例如
- 内存释放机制:手动调用对象的析构函数
obj->~MyClass();
,然后释放内存池delete[] buffer;
- 相较于普通new的优势:减少频繁的堆内存分配和释放,提高性能,降低内存碎片化。
- 可能带来的问题:需要手动管理内存池的大小和对象的析构,增加了代码复杂性,如果析构函数调用不当可能导致内存泄漏。
场景二:共享内存
- 使用方法:
- 获取共享内存地址,例如通过系统调用获取共享内存段指针
void* sharedMem = shmat(shmid, nullptr, 0);
- 使用
placement new
在共享内存上构造对象:MyClass* sharedObj = new (sharedMem) MyClass();
- 获取共享内存地址,例如通过系统调用获取共享内存段指针
- 内存释放机制:手动调用对象析构函数
sharedObj->~MyClass();
,然后分离共享内存shmdt(sharedMem);
- 相较于普通new的优势:能够直接在共享内存上构造对象,方便进程间数据共享,避免了不必要的内存拷贝。
- 可能带来的问题:共享内存的管理需要遵循系统特定的规则,跨进程对象的生命周期管理复杂,容易出现同步问题。
4. 正确使用placement new及注意事项
- 正确使用:确保提供的内存地址有足够的空间容纳要构造的对象,并且该内存地址的对齐方式符合对象的要求。构造对象后,手动调用析构函数来销毁对象。
- 注意事项:不要在同一个已构造对象的内存位置重复使用
placement new
,除非先调用析构函数。同时,使用placement new
构造的对象,内存释放必须手动管理,否则会导致内存泄漏。