【问题标题】:Uniqueness of std::unique_ptrstd::unique_ptr 的唯一性
【发布时间】:2014-05-18 00:56:30
【问题描述】:

我一直在研究 std::unique_ptr ,但在某些时候对它的语义感到困惑。来自documentation

No two unique_ptr instances can manage the same object

但是,即使很难,它也很可能是一个愚蠢的例子,请考虑这样的代码。

std::unique_ptr<int> a(new int(10));
std::unique_ptr<int> b = std::unique_ptr<int>(a.get());
std::cout << *b << std::endl;
*a = 5;
std::cout << *b;

a 和 b 在这里管理同一个对象,输出为 10 5。当然,由于两个唯一的 ptrs 试图在范围。

我知道这很愚蠢并且不建议使用这种用法,但是当它不是很明显时我遇到了这个(一个类成员调用另一个等)并且断言失败是我开始的事情。

我的问题是上面这句话的确切含义:它是由标准提出的,一个体面的编译器不应该允许你这样做(我在 vs2013 顺便说一句)或者你必须这样做(永远不要导致两个 unique_ptrs 指向同一个对象)(不太可能,因为我想 unique_ptrs 的目的是让我们不那么担心。)或者当涉及到 unique_ptr 时,我不应该使用任何关于原始指针(a.get())的东西。

【问题讨论】:

    标签: c++11 unique-ptr


    【解决方案1】:

    你的最后一句话是正确的。一旦你使用原始指针和a.get() 如下行所示,你已经抛弃了std::unique_ptr 对你做出的所有承诺。

    std::unique_ptr<int> b = std::unique_ptr<int>(a.get());
    

    在转换为原始指针时保持唯一性的正确语义是使用a.release()

    std::unique_ptr<int> b = std::unique_ptr<int>(a.release());
    

    当然,如果您在两个std::unique_pointer 实例之间移动所有权,您通常只需使用std::move 的赋值或初始化,正如documentation 所给出的那样。以下两行中的任何一行都应该是有效的。

    std::unique_ptr<int> b(std::move(a));
    std::unique_ptr<int> b = std::move(a);
    

    为了使std::move 语义更加清晰,请考虑以下测试程序。

    #include <stdio.h>
    #include <memory>
    #include <stdlib.h>
    
    
    int main(){
        std::unique_ptr<int> a(new int(10));
        printf("%p\n", a.get());
        std::unique_ptr<int> b(std::move(a));
        printf("%p\n", a.get());
        printf("%p\n", b.get());
    }
    

    在我的系统上,输出如下。观察第一行和最后一行匹配。

    0x1827010
    (nil)
    0x1827010
    

    【讨论】:

    • 您需要使用std::unique_ptr&lt;int&gt; b = std::move(a);。您必须对 std::unique_ptr 使用移动分配。
    • @ECrownofFire,正在修复,谢谢...我应该检查一下。
    • 我很难理解移动语义。据我了解,这条线将使 b 指向 a 指向的任何内容,并指向 null,对吗?
    • @bahti,粗略地说,是的。 This question 提供更多细节。
    • 您提供的链接真的很有帮助,谢谢。但现在我想到了具有唯一 ptr 成员的类的复制构造函数。如果 unique_ptr 是指向派生类的基类指针,我们不能使用 ( new Base(*foo.uniqueptrmember) 或 this.uniquptrmember = std::move(foo.uniqueptrmember) 因为 foo 是常量。可能的解决方案是什么?
    猜你喜欢
    • 2019-11-07
    • 2017-12-18
    • 1970-01-01
    • 2022-08-04
    • 2014-03-27
    • 2020-04-17
    • 1970-01-01
    • 2011-03-27
    • 1970-01-01
    相关资源
    最近更新 更多