首页 > 解决方案 > 唯一指针初始化

问题描述

我还是 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函数,然后是一个获取数据的函数。
不过感觉不对。

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

谢谢,
内森

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

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

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

谢谢

标签: c++smart-pointers

解决方案


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

这不是在正常情况下发生的事情。

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

当 aunique_ptr持有nullptr时,reset()是一个空操作。分配给unique_ptr正在持有的 a 是完全安全的nullptr

即使reset()不是无操作,调用delete.nullptr

也就是说,在分配给时唯一Dummy可以调用的析构函数是在不持有 a时。为了在您显示的构造函数中发生这种情况,必须处于无效状态,因为:m_Dummym_DummynullptrTestm_Dummy

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

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


推荐阅读