提问者:小点点

std::unique_ptr的唯一性


我一直在研究std::unique_ptr,但在某个时候对它的语义感到困惑。从文档中可以看出,

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。当然,由于两个唯一的PTR试图在作用域末尾销毁相同的对象,我在调试模式末尾会出现断言失败错误。

我知道这很愚蠢,也不建议这样的用法,但是当它不是很明显(类成员调用另一个类成员等)并且断言失败是我开始的时候,我就意识到了这一点。

我的问题是上面这句话的确切含义:它是由标准提出的,一个像样的编译器不应该允许你这样做(我在vs2013 btw上)或者你必须这样做(永远不要导致两个unique_ptrs指向同一个对象)(不太可能,因为unique_ptrs的目的是让我们少担心我想)或者,当涉及时,我不应该使用任何有关原始指针()的内容。


共1个答案

匿名用户

你的最后一句话是正确的。当您在中使用原始指针(如下行所示)时,您就抛弃了对您做出的所有承诺。

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

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

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

当然,如果要在两个实例之间移动所有权,通常只需使用赋值或初始化即可,如文档所示。下面两行中的任何一行都应该有效。

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

为了使语义更加清晰,请考虑下面的测试程序。

#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