示例代码:
#include<memory>
#include<iostream>
int main()
{
std::unique_ptr<int> intPtr{new int(3)};
int* myPtr = intPtr.get();
*myPtr = 4;
std::cout<<"New result for intPtr: "<< *intPtr.get()<<std::endl;
}
这不是违背了std::unique_ptr
背后的全部目的吗?为什么这是允许的?
编辑:我认为std::unique_ptr背后的全部目的是拥有对象的唯一所有权。但是在本例中,对象可以通过另一个指针进行修改。这不是违背了std::unique_ptr的目的吗?
虽然智能指针管理被指向对象的生命周期,但访问底层原始指针通常仍然是有用的。
事实上,如果我们阅读Herb Sutter的GotW #91解决方案:智能指针参数,他建议通过指针或引用传递参数,当函数对参数的生命周期不可知时,他说:
忽略*或&独立于调用者如何接受小部件管理其生命周期。大多数时候,我们不想承诺参数类型中的生存期策略,例如要求对象为由一个特定的智能指针持有,因为这通常是不必要的限制。
,当函数是sink时,应该通过unique_ptr传递:
按值传递unique_ptr对象只能通过移动对象来实现以及从调用方到被调用方的唯一所有权。任何函数(c)从调用者手中夺走了对象的所有权,并且要么销毁它,要么把它转移到其他地方。
,最后通过引用传递unique_ptr
,当我们可能修改它以引用不同的对象时:
这应该只用于接受输入/输出unique_ptr,当函数应该实际接受一个已存在的unique_ptr和可以将其修改为引用不同的对象。这是一种不好的方式只是接受一个小部件,因为它被限制在一个特定的调用者的生命周期策略。
当然,如果必须与接受指针的C库接口,则需要获得底层指针。
在你的具体例子中:
int* myPtr = intPtr.get();
没有所有权转移到另一个智能指针,所以没有问题,只要你不试图通过myPtr
delete
指针。您可以将所有权转移到另一个unique_ptr
通过移动它:
std::unique_ptr<int> intPtr2( std::move( intPtr ) ) ;
您所展示的示例并没有破坏std::unique_ptr
的目的,即维护内存分配和释放的所有权。行std::unique_ptr<int> intPtr{new int(3)}
分配一个新的int
并占有它。
*myPtr = 4
行不改变所有权,它只是通过std::unique_ptr::get()
检索的指针将值赋给int
的内容。std::unique_ptr
仍然拥有为int
分配的内存
这完全没有违背unique_ptr
的目的。智能指针的类型决定了所有权语义,但在某些情况下,您可能需要使用底层对象。例如,您有一个由unique_ptr
拥有的对象,但需要调用一个通过引用期望该对象的方法。然后,您可以解引用.get()
指针,以获得要传递给方法的引用对象。
不应该以获取所有权的方式存储获得的指针。这是语言为你提供工具来正常工作的一种情况,如果你使用原始指针并为它存储第二个所有权,那么这是使用工具的一个问题。
Get只允许您获取原始指针。否则,当您有unique_ptr
时,您将无法使用基于指针的API,因为唯一的替代方案是release
,这将使唯一指针无用。所以你得到了get
,它允许使用基于指针的api,而不强迫每个人都使用unique_ptr
。如果没有get
,你只能在指针上调用->和*,但是如果你有一个基本类型,那首先就会有一个unique_ptr
。