Sil*_*lan 2 c++ move unique-ptr c++14
我想将NULL std :: unique_ptr移至std :: shared_ptr,如下所示:
std::unique_ptr<float> test = nullptr;
std::shared_ptr<float> test2 = std::move(test);
Run Code Online (Sandbox Code Playgroud)
据我所知,这样做是合法的,并且在Visual Studio 2015和GCC中运行良好。
但是,我不能对具有删除器声明的std :: unique_ptr进行相同操作,如下所示:
std::unique_ptr<float,void(*)(float*)> test = nullptr;
std::shared_ptr<float> test2 = std::move(test);
Run Code Online (Sandbox Code Playgroud)
上面的代码将无法在Visual Studio中编译,并且将触发静态断言失败“错误C2338:使用空删除器指针构造的unique_ptr”。
我可以改用std :: function删除器,在这种情况下,可以避免静态断言失败:
std::unique_ptr<float,std::function<void(float*)>> test = nullptr;
std::shared_ptr<float> test2 = std::move(test);
Run Code Online (Sandbox Code Playgroud)
在这种情况下,代码可以正常编译,但是一旦销毁了test2的最后一个std :: shared_ptr副本,我就会中止运行。
为什么后两种情况如此成问题?
奇怪的是,如果我将test2的类型从std :: shared_ptr更改为std :: unique_ptr,则第二种情况仍然会触发静态断言失败,但是情况1和情况3都可以正常工作:
{
std::unique_ptr<float> test = nullptr;
std::unique_ptr<float> test2 = std::move(test); // Works fine
}
{
//std::unique_ptr<float,void(*)(float*)> test = nullptr; // triggers a static assert failure
//std::unique_ptr<float,void(*)(float*)> test2 = std::move(test);
}
{
std::unique_ptr<float,std::function<void(float*)>> test = nullptr;
std::unique_ptr<float,std::function<void(float*)>> test2 = std::move(test); // Works fine
}
Run Code Online (Sandbox Code Playgroud)
在unique_ptr你正在试图使用构造函数,它默认构造删除器,是形成不良的(前C ++ 17)或禁用由SFINAE(作为C ++ 17),如果删除器类型是指针,以停止您不小心创建了一个unique_ptr删除器,其删除器本身就是一个空指针。如果您确实要创建这样的unique_ptr,则可以通过显式传递null删除器来实现:
std::unique_ptr<float,void(*)(float*)> test(nullptr, nullptr);
Run Code Online (Sandbox Code Playgroud)
该unique_ptr对象不是很有用,因为它无法删除任何内容。
通过使用空std::function删除器,您已经告诉编译器“是的,我真的很想自杀”。当然,当最后一个std::shared_ptr销毁时,将std::function调用null 并发生未定义的行为。您还期望什么?