唯一指针初始化

Unique Pointer Initialization

我还是 c++ 的新手,如果这很明显,我深表歉意,但经过大量谷歌搜索后我找不到好的答案。
我希望我能写出下面的代码。

class Test {
public:
    Test();

private:
    std::unique_ptr<Dummy> m_Dummy;
};
Test::Test() {
    auto data = // generate some data here
    m_Dummy = std::make_unique<Dummy>(data);
}

会发生什么:
m_Dummy 上的赋值运算符调用 unique_ptr::reset
在指针上调用 delete,
它调用 m_Dummy 析构函数,
运行 析构函数创建了一个段错误,因为它从未被初始化。

正确的方法是在构造函数初始化列表中进行初始化。
但是这样我就无法传入我想要的数据了。

Test::Test() : m_Dummy{std::make_unique<Dummy>(data)} { // Don't have time to generate data
}

我不知道如何让这个更干净。
我目前的想法是将 Dummy 更改为具有默认构造函数,然后是一个 initialize 函数来获取数据。
不过感觉不对。

有没有更简洁的方法来处理这个问题?
需要参数并且还需要是class成员的智能指针通常会做什么?

谢谢,
内森

编辑:
从下面的答案来看,我的代码中某处可能存在完全不同的问题。
这是在抛出段错误之前来自调试器的调用堆栈。

Dummy::~Dummy Dummy.cpp:24
std::default_delete<Dummy>::operator() unique_ptr.h:78
std::unique_ptr<Dummy, std::default_delete<Dummy> >::reset unique_ptr.h:371
std::unique_ptr<Dummy, std::default_delete<Dummy> >::operator= unique_ptr.h:278
Test::Test Test.cpp:42
std::make_unique<Test, int&, double, double> unique_ptr.h:821
World::World World.cpp:25
Application::Run Application.cpp:77
main main.cpp:10
__libc_start_main 0x00007fbd47bbdb97
_start 0x0000555e1df657ea

编辑2:
问题是在创建我的数据的过程中,我破坏了我的记忆,而 Dummy 恰好是受害者。 我最初创建 unique_ptr 的提议现在有效了。

谢谢

创建一个 static 方法来生成数据?

class Test {
public:
    Test();

private:
    static Dummy makeConstructionData()
    {
      return Dummy();
    }
    std::unique_ptr<Dummy> m_Dummy;
};

之后你可以做:

Test::Test() : m_Dummy{std::make_unique<Dummy>(makeConstructionData())} { 
}

What happens:
The assignment operator on m_Dummy calls unique_ptr::reset, which calls delete on the pointer, which calls the m_Dummy destructor, and running the destructor creates a segfault because it was never initialized.

正常条件下不会发生这种情况。

m_Dummy 未在 Test 构造函数中 显式 初始化,因此它会 隐式 默认构造相反,它的默认构造函数将其持有的指针设置为 nullptr.

unique_ptr 持有 nullptr 时,reset() 是空操作。分配给持有 nullptr.

unique_ptr 是完全安全的

即使 reset() 不是空操作,在 nullptr.

上调用 delete 也是绝对安全的

也就是说,在给 m_Dummy 赋值时调用 Dummy 的析构函数的唯一方法是当 m_Dummy 没有持有 nullptr 时。要在您显示的 Test 构造函数中发生这种情况,m_Dummy 必须处于无效状态,因为:

  • 在无效内存上调用了 Test 构造函数(不太可能,除非您滥用 placement-new

  • 你初始化 data 的代码,甚至 Dummy 构造函数本身,正在破坏随机内存,而 m_Dummy 是这种破坏的不知情的受害者(更有可能)。