我试图了解现代 C++ 中唯一指针的工作原理。
当我浏览文档(cppreference 和其他文档)时,我能够理解这unique_ptr将转移所有权而不是共享它。但我不明白为什么unique_ptr在使用传递到其构造函数的原始指针时表现得很奇怪。
例如:
#include <iostream>
#include <memory>
class foo{
int x;
public:
foo(): x(0) {}
foo(int a): x(a) {}
foo(const foo& f): x(f.x) {}
};
int main(){
foo *ptr = new foo(5);
std::unique_ptr<foo> uptr(ptr);
std::cout << ptr << "\n";
std::cout << uptr.get() << "\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出如下:
0x5c7bc80
0x5c7bc80
Run Code Online (Sandbox Code Playgroud)
查询:
=delete)?为什么原始指针打印的地址与 相同unique_ptr?unique_ptr?std::make_unique()?我尝试更改线路std::unique_ptr<foo> uptr(ptr);但std::unique_ptr<foo> uptr(std::make_unique<foo>(*ptr));没有任何改变。原始指针是否被传递到复制构造函数中?
不是复制构造函数,不(需要另一个unique_ptr作为输入)。相反,原始指针被传递给转换构造函数,特别是在本例中:
explicit unique_ptr( pointer p ) noexcept;
Run Code Online (Sandbox Code Playgroud)
复制构造函数不是被删除了吗(
=delete)?
是的。但这段代码没有调用复制构造函数。
为什么原始指针打印与 相同的地址
unique_ptr?
因为它unique_ptr只是将输入指针按原样复制到其自己的内部成员指针中,从而获得所指向的对象的所有权。您正在打印两个指针的值,它们具有相同的值,因为它们指向内存中的同一个对象。
这是设计缺陷吗
unique_ptr?
不。
我该如何克服这个问题?
什么问题?这里没有问题。其unique_ptr行为符合设计。
有什么用
std::make_unique()?
为了更有效地分配内存,请在该内存中构造一个对象,并使用 new 获取该内存的所有权unique_ptr,所有这些都在一个操作中完成。
我尝试更改线路
std::unique_ptr<foo> uptr(ptr);但std::unique_ptr<foo> uptr(std::make_unique<foo>(*ptr));没有任何改变。
应该有。
该表达式std::make_unique<foo>(*ptr)正在创建一个与所指向的foo对象分离的新对象。ptr它将把取消引用的*ptr对象传递给新foo对象的复制构造函数。
然后,在表达式 中std::unique_ptr<foo> uptr(...);,uptr移动返回unique_ptr的make_unique(),它指向新foo对象。所以uptr现在拥有该foo对象。
随后,您的 2 个打印应该输出不同的值,因为ptr和uptr指向不同的foo对象。
请注意,在这种情况下,您将泄漏所指向的foo对象,因为没有人取得该对象的所有权。所以你有责任手动进行它。ptrunique_ptrdelete
这段代码:
foo *ptr = new foo(5);
std::unique_ptr<foo> uptr(ptr);
Run Code Online (Sandbox Code Playgroud)
可以改为这样:
std::unique_ptr<foo> uptr = std::make_unique<foo>(5);
Run Code Online (Sandbox Code Playgroud)
或者:
auto uptr = std::make_unique<foo>(5);
Run Code Online (Sandbox Code Playgroud)
std::make_unique()分配并构造其模板参数中指定的类型,将输入参数传递给该对象的构造函数。