假设我在C ++中有以下代码:
#include <memory>
#include <iostream>
struct Some {
Some(int _a) : a(_a) {}
int a;
};
int main() {
Some some(5);
std::unique_ptr<Some> p1 = std::make_unique<Some>(some);
std::unique_ptr<Some> p2 = std::make_unique<Some>(some);
std::cout << p1->a << " " << p2->a << std::endl;
return 0;
}
据我所知,使用唯一指针来保证资源不被共享。但在这种情况下,p1
和p2
都指向同一个实例some
。
请揭开情况。
答案 0 :(得分:26)
他们没有指向相同的资源,他们每个都指向不同的副本。您可以通过删除复制构造函数来说明错误:
#include <memory>
#include <iostream>
struct Some {
Some(int _a) : a(_a) {}
Some(Some const&) = delete;
int a;
};
int main() {
Some some(5);
std::unique_ptr<Some> p1 = std::make_unique<Some>(some); //error here
std::unique_ptr<Some> p2 = std::make_unique<Some>(some);
std::cout << p1->a << " " << p2->a << std::endl;
return 0;
}
答案 1 :(得分:16)
std::make_unique
创建对象,使用指定的参数调用构造函数。
您传递Some&
作为参数,此处调用了复制构造函数,并构造了新对象。
所以,p1和p2是两个完全不同的指针,但是使用复制构造函数从同一个对象构造
答案 2 :(得分:9)
p1
和p2
都指向同一个实例some
#include <memory>
#include <iostream>
struct Some {
Some(int _a) : a(_a) {}
int a;
};
int main() {
Some some(5);
std::unique_ptr<Some> p1 = std::make_unique<Some>(some);
std::unique_ptr<Some> p2 = std::make_unique<Some>(some);
std::cout << p1->a << " " << p2->a << std::endl;
p1->a = 42;
std::cout << p1->a << " " << p2->a << std::endl;
return 0;
}
输出:
5 5
42 5
答案 3 :(得分:1)
要测试两个指针是否指向同一个对象实例,您应该比较它们指向的位置,而不是对象成员变量:
std::cout << &(*p1) << " " << &(*p2) << std::endl;
这将表明他们确实不指向同一个实例。
ADDENDUM:正如Remy Lebeau所指出的那样,从C ++ 11开始,建议使用
std::addressof
用于此目的,即使&
运算符过载,也会获取对象的实际地址:
std::cout << std::addressof(*p1) << " " << std::addressof(*p2) << std::endl;