C++20下向std::vector<unique_ptr<Object>>添加元素的最优安全方式
向存储
std::unique_ptr<Object>的std::vector添加元素的最优安全方案 首先明确:绝对要避免的写法
vec.emplace_back(new Object) 这种写法存在内存泄漏风险,是不安全的。原因是:当vector需要扩容时,会先尝试分配新内存,如果分配失败抛出异常,此时new Object已经创建了对象,但std::unique_ptr还没完成构造,无法接管对象所有权,导致对象内存直接泄漏。
合规且安全的核心方案
所有安全方案的核心都是让std::unique_ptr立刻接管新创建的Object,避免裸指针暴露的风险。优先使用std::make_unique(C14及以上支持,你的G11.1.0完全兼容):
1. 使用std::make_unique配合emplace_back或push_back
这两种写法在C++20下效率几乎无差异,都是安全的:
vec.emplace_back(std::make_unique<Object>());emplace_back会完美转发std::make_unique返回的右值unique_ptr,原地移动构造vector中的元素,无额外拷贝开销。vec.push_back(std::make_unique<Object>());push_back接受右值引用,同样会移动构造元素,效果和上面一致。
如果Object需要构造参数,直接传递给make_unique即可:
vec.emplace_back(std::make_unique<Object>(arg1, arg2));
2. 仅添加空unique_ptr的场景
你提到的vec.emplace_back()是完全合规的,它会默认构造一个空的std::unique_ptr<Object>(指向nullptr)。但注意这种写法不会创建任何Object实例,仅适用于需要添加空智能指针的场景。
emplace_back vs push_back的选择
在C++20中,对于std::unique_ptr这类仅支持移动语义的类型:
- 当传递右值(比如
std::make_unique的返回值)时,emplace_back和push_back的效率完全一致,都是移动构造元素,没有性能差异。 emplace_back的优势在于可以原地构造元素,但对于unique_ptr来说,直接传递裸指针会回到泄漏风险,所以还是配合make_unique使用更安全。
总结:优先选择std::make_unique配合emplace_back或push_back,两者都是最优且安全的写法,根据个人习惯选择即可。
内容的提问来源于stack exchange,提问作者spaL
相关产品推荐
相关产品推荐

