唯一指针初始化
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
是这种破坏的不知情的受害者(更有可能)。
我还是 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 onm_Dummy
callsunique_ptr::reset
, which callsdelete
on the pointer, which calls them_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
是这种破坏的不知情的受害者(更有可能)。