You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

std::unique_ptr重赋值时能否先销毁旧值再构造新对象?

解决方案

标准库目前没有内置名为replace_unique的接口,但你可以自行实现一个零开销的工具函数满足需求,核心逻辑就是显式先销毁旧对象,再创建新对象:

#include <memory>
#include <utility>

template<typename T, typename... Args>
void replace_unique(std::unique_ptr<T>& ptr, Args&&... args)
{
    // 第一步:释放旧对象占有的内存
    ptr.reset();
    // 第二步:构造新对象并赋值
    ptr = std::make_unique<T>(std::forward<Args>(args...));
}

使用示例

你原来的refresh_foo函数可以改写为:

void MyClass::refresh_foo(int x) {
    replace_unique(m_foo, x * 3 + 5);
}

如果不想封装函数,直接写两行代码效果完全一致:

void MyClass::refresh_foo(int x) {
    m_foo.reset();
    m_foo = std::make_unique<int>(x * 3 + 5);
}

关键说明

  1. 内存占用符合要求:该实现会先完全释放旧对象的内存,再分配新对象的内存,不会出现两个大对象同时占用内存的情况,生成的汇编代码和你提到的原生指针旧实现几乎没有差异,无额外运行时开销。
  2. 安全性优于原生指针实现:原生指针版本如果new阶段抛出异常,m_foo会成为野指针;而该实现中就算make_unique抛出异常,m_foo也只会处于合法的空指针状态,不会出现内存安全问题。
  3. 异常安全权衡:标准库默认的operator=和reset采用「先构造新对象、再销毁旧对象」的顺序,是为了提供强异常安全保证:如果新对象构造失败,原指针的内容会完全保留。你需要的优先优化内存的实现只提供基本异常安全保证:新对象构造失败时指针会变为空,你需要确认业务逻辑可以接受这个后果。

内容的提问来源于stack exchange,提问作者Remy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 13:06:00