示例代码:
#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的目的吗?
答案 0 :(得分:13)
虽然Smart pointers管理被指向对象的生命周期,但访问底层原始指针通常仍然很有用。
事实上,如果我们阅读Herb Sutter的GotW #91 Solution: Smart Pointer Parameters,他建议当函数与参数的生命周期无关时,通过指针或引用传递参数,他说:
通过*或&amp;独立于调用者的方式接受窗口小部件 管理它的一生。大多数时候,我们不想承诺 参数类型中的生命周期策略,例如要求对象为 由特定的智能指针持有,因为这通常是不必要的 限制性的。
当函数是接收器时,我们应该通过unique_ptr:
只能通过移动对象来传递unique_ptr by value 以及从呼叫者到被呼叫者的独特所有权。任何功能 像(c)取得对象的所有权远离来电者,和 要么将其摧毁,要么将其向前移动到其他地方。
最后通过引用传递unique_ptr
,我们可能会修改它以引用不同的对象:
这应该只用于接受输入/输出unique_ptr,当 函数应该实际接受现有的unique_ptr和 可能会修改它以引用不同的对象。这是一个糟糕的方式 只接受一个小部件,因为它仅限于特定的 来电者的终身策略。
当然,如果我们必须与带有指针的C库接口,我们需要获取底层指针。
在您的具体示例中:
int* myPtr = intPtr.get();
没有所有权转移到另一个智能指针,因此只要您不通过delete
尝试myPtr
指针就没有问题。您可以通过移动来将所有权转移到另一个unique_ptr
:
std::unique_ptr<int> intPtr2( std::move( intPtr ) ) ;
答案 1 :(得分:7)
这根本没有打败unique_ptr
的目的。智能指针的类型决定了所有权语义,但可能存在需要使用底层对象的情况。例如,您有一个由unique_ptr
拥有的对象,但需要通过引用调用期望该对象的方法。然后,您可以取消引用.get()
指针以获取要传递给方法的引用对象。
不应做的是以获取所有权的方式存储获取的指针。这是语言为您提供正常工作的工具之一,如果您使用原始指针并存储第二个所有权,那么使用该工具就会出现问题。
答案 2 :(得分:5)
您展示的示例并没有违背std::unique_ptr
的目的,即维护内存分配和释放的所有权。第std::unique_ptr<int> intPtr{new int(3)}
行分配了一个新的int
并获得了它的所有权。
行*myPtr = 4
不会更改该所有权,只需通过int
检索到的指针为std::unique_ptr::get()
的内容指定值。 std::unique_ptr
仍然拥有int
的已分配内存。
答案 3 :(得分:3)
Get只允许您获取原始指针。否则,当您拥有unique_ptr
时,您将无法使用基于指针的API,因为唯一的选择是release
,这会使唯一指针无效。所以你得到get
,它允许使用基于指针的API,而不必强迫每个人都使用unique_ptr
。如果没有get
,则只能调用 - &gt;和*在指针上,但如果你有一个原始类型,那将首先失去unique_ptr
。