具有右值删除器的 unique_ptr 构造函数返回 null?

Posted

技术标签:

【中文标题】具有右值删除器的 unique_ptr 构造函数返回 null?【英文标题】:unique_ptr constructor with rvalue deleter returns null? 【发布时间】:2018-01-12 02:22:55 【问题描述】:

这是我用来理解std::unique_ptr行为的代码sn-p:

std::default_delete<int> d;
std::unique_ptr<int> u1;
std::unique_ptr<int> u2 (nullptr);
std::unique_ptr<int> u3 (new int);
std::unique_ptr<int> u4 (new int, d);
std::unique_ptr<int> u5 (new int, std::default_delete<int>());
std::unique_ptr<int> u6 (std::move(u5));
std::unique_ptr<int> u7 (std::move(u6));
std::unique_ptr<int> u8 (std::auto_ptr<int>(new int));

std::cout << "u1: " << (u1?"not null":"null") << '\n';
std::cout << "u2: " << (u2?"not null":"null") << '\n';
std::cout << "u3: " << (u3?"not null":"null") << '\n';
std::cout << "u4: " << (u4?"not null":"null") << '\n';
std::cout << "u5: " << (u5?"not null":"null") << '\n';
std::cout << "u6: " << (u6?"not null":"null") << '\n';
std::cout << "u7: " << (u7?"not null":"null") << '\n';
std::cout << "u8: " << (u8?"not null":"null") << '\n';

有人能解释为什么null 被打印为u5u6,而不是u7?提前致谢!

【问题讨论】:

std::unique_ptr 始终只有一个所有者。当您移动所有权时,原始指针变为空。因此,如果您在某个声明之间插入打印语句,那么当值变为空时会变得很明显。使用调试器是帮助理解代码的另一种方法就像阅读文档一样 非常感谢您的解释,我一直在想为什么,现在我明白了。 【参考方案1】:

正如 Phil1970 在他的评论中指出的那样,std::unique_pointer 实例在分配给另一个实例后变为(等效于)nullptr(使用 std::move,如您的代码示例中所示)。实际上,这就是 std::unique_ptr 的用途。它是独一无二的。

现在考虑这段代码:

#include <memory>
#include <iostream>

int main()

    std::default_delete<int> d;
    std::unique_ptr<int> u1;
    std::cout << "u1: " << (u1 ? "not null" : "null") << '\n';

    std::unique_ptr<int> u2(nullptr);
    std::cout << "u2: " << (u2 ? "not null" : "null") << '\n';

    std::unique_ptr<int> u3(new int);
    std::cout << "u3: " << (u3 ? "not null" : "null") << '\n';

    std::unique_ptr<int> u4(new int, d);
    std::cout << "u4: " << (u4 ? "not null" : "null") << '\n';

    std::unique_ptr<int> u5(new int, std::default_delete<int>());
    std::cout << "u5: " << (u5 ? "not null" : "null") << '\n';

    std::unique_ptr<int> u6(std::move(u5));
    std::cout << "u6: " << (u6 ? "not null" : "null") << '\n';

    std::unique_ptr<int> u7(std::move(u6));
    std::cout << "u7: " << (u7 ? "not null" : "null") << '\n';

当executed 实例化后,您会立即看到u5u6 为“非空”。

【讨论】:

以上是关于具有右值删除器的 unique_ptr 构造函数返回 null?的主要内容,如果未能解决你的问题,请参考以下文章

如何在构造函数中使用删除器初始化 std::unique_ptr?

C++11之右值引用:移动语义和完美转发(带你了解移动构造函数纯右值将亡值右值引用std::moveforward等新概念)

当成员是unique_ptr时删除了复制构造函数[重复]

为什么`std :: pair`允许使用用户定义的删除移动构造函数从类类型的右值初始化?

unique_ptr & vector,试图访问已删除的函数,Visual Studio 2013

[C++11]独占的智能指针unique_ptr的删除器