我一直在研究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 btw上)或者你必须这样做(永远不要让两个unique_ptrs指向同一个对象)(不太可能,因为unique_ptrs的目的是让我们不那么担心我的想法。)或者当涉及a.get()
时,我永远不应该使用关于原始指针(unique_ptr
)的任何内容。
答案 0 :(得分:2)
你的最后一句话是对的。一旦你使用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::move
实例之间移动所有权,通常只需使用std::unique_pointer
进行分配或初始化,如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