Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Doesn't get() break the idea behind std::unique_ptr?

Example code:

#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;

}

Doesn't this defeat the whole purpose behind std::unique_ptr ? Why is this allowed?

Edit: I thought the whole purpose behind std::unique_ptr was to have sole ownership of an object. But this example, the object can be modified through another pointer. Doesn't this defeat std::unique_ptr's purpose?

like image 572
wizurd Avatar asked Aug 18 '14 19:08

wizurd


1 Answers

While Smart pointers manage the lifetime of an object being pointed to, it is often still useful to have access to the underlying raw pointer.

In fact if we read Herb Sutter's GotW #91 Solution: Smart Pointer Parameters he recommends passing parameters by pointer or reference when the function is agnostic to the lifetime of the parameter, he says:

Pass by * or & to accept a widget independently of how the caller is managing its lifetime. Most of the time, we don’t want to commit to a lifetime policy in the parameter type, such as requiring the object be held by a specific smart pointer, because this is usually needlessly restrictive.

and we should pass by unique_ptr when the function is a sink:

Passing a unique_ptr by value is only possible by moving the object and its unique ownership from the caller to the callee. Any function like (c) takes ownership of the object away from the caller, and either destroys it or moves it onward to somewhere else.

and finally pass a unique_ptr by reference when we can potentially modify it to refer to a different object:

This should only be used to accept an in/out unique_ptr, when the function is supposed to actually accept an existing unique_ptr and potentially modify it to refer to a different object. It is a bad way to just accept a widget, because it is restricted to a particular lifetime strategy in the caller.

Of course, we are required to get the underlying pointer if we have to interface with C libraries that take pointers.

In your specific example:

int* myPtr = intPtr.get();

There is no transfer of ownership to another smart pointer so there are no problems as long as you don't attempt to delete the pointer via myPtr. You can transfer ownership to another unique_ptr by moving it:

std::unique_ptr<int> intPtr2( std::move( intPtr ) ) ;
like image 108
Shafik Yaghmour Avatar answered Oct 22 '22 15:10

Shafik Yaghmour