首页 > 解决方案 > 是否可以重新分配 std::unique_ptr 以使其旧值在构造新值之前*被销毁?

问题描述

我有兴趣将旧的个人项目更新为现代 C++。我很欣赏 RAII 如何简化清理:与其在函数中的每个返回点之前创建一个new对象并记住它,不如将它适当地销毁。但是在比较生成的程序集时我有一个挑剔。deletemake_unique

假设有一个类方法将其unique_ptr成员之一替换为新值:

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

这将创建一个new int,将其分配给m_foo,然后delete是 的旧值m_foo。但这与旧行为不太一样,旧行为可能delete是旧值,然后创建new一个并将其分配给m_foo

// int *MyClass::m_foo;
void MyClass::refresh_foo(int x) {
    delete m_foo;
    m_foo = new int(x * 3 + 5);
}

Compiler Explorer中,gcc、clang 和 MSVC 为旧方式生成的代码都比新方式少。我理解为什么会这样,因为这是评估所有表达式的顺序;p = q;必须先建造q。当然,在和行m_foo之间有一个无效值。但是有没有一种方法可以让我破坏它的旧值,然后在一个表达式中创建一个新的?一个“ ”?似乎在处理大型对象时会有所帮助,因此它们中的两个不会不必要地共存。deletenewunique_ptrreplace_unique

编辑:为了清楚起见,我只是int在这里用作一个简单的例子。我的实际用例是我自己的类或库中的类。与m_foo.reset(new int(x * 3 + 5));旧的做事方式相比,自然有同样的问题,因为它也必须new int在分配它之前构造 the 和deleting 前一个。

标签: c++destructorsmart-pointersunique-ptr

解决方案


您可以根据unique_ptr::reset()需要确定性地销毁当前持有的对象。unique_ptr用一个指针更新nullptr它,然后用一个新的对象指针更新它,例如:

// std::unique_ptr<int> MyClass::m_foo;
void MyClass::refresh_foo(int x) {
    m_foo.reset(); // <- int is destroyed here
    m_foo = std::make_unique<int>(x * 3 + 5);
}

推荐阅读