How to declare std::unique_ptr and what is the use of it?

170,534

Solution 1

The constructor of unique_ptr<T> accepts a raw pointer to an object of type T (so, it accepts a T*).

In the first example:

unique_ptr<int> uptr (new int(3));

The pointer is the result of a new expression, while in the second example:

unique_ptr<double> uptr2 (pd);

The pointer is stored in the pd variable.

Conceptually, nothing changes (you are constructing a unique_ptr from a raw pointer), but the second approach is potentially more dangerous, since it would allow you, for instance, to do:

unique_ptr<double> uptr2 (pd);
// ...
unique_ptr<double> uptr3 (pd);

Thus having two unique pointers that effectively encapsulate the same object (thus violating the semantics of a unique pointer).

This is why the first form for creating a unique pointer is better, when possible. Notice, that in C++14 we will be able to do:

unique_ptr<int> p = make_unique<int>(42);

Which is both clearer and safer. Now concerning this doubt of yours:

What is also not clear to me, is how pointers, declared in this way will be different from the pointers declared in a "normal" way.

Smart pointers are supposed to model object ownership, and automatically take care of destroying the pointed object when the last (smart, owning) pointer to that object falls out of scope.

This way you do not have to remember doing delete on objects allocated dynamically - the destructor of the smart pointer will do that for you - nor to worry about whether you won't dereference a (dangling) pointer to an object that has been destroyed already:

{
    unique_ptr<int> p = make_unique<int>(42);
    // Going out of scope...
}
// I did not leak my integer here! The destructor of unique_ptr called delete

Now unique_ptr is a smart pointer that models unique ownership, meaning that at any time in your program there shall be only one (owning) pointer to the pointed object - that's why unique_ptr is non-copyable.

As long as you use smart pointers in a way that does not break the implicit contract they require you to comply with, you will have the guarantee that no memory will be leaked, and the proper ownership policy for your object will be enforced. Raw pointers do not give you this guarantee.

Solution 2

There is no difference in working in both the concepts of assignment to unique_ptr.

int* intPtr = new int(3);
unique_ptr<int> uptr (intPtr);

is similar to

unique_ptr<int> uptr (new int(3));

Here unique_ptr automatically deletes the space occupied by uptr.


how pointers, declared in this way will be different from the pointers declared in a "normal" way.

If you create an integer in heap space (using new keyword or malloc), then you will have to clear that memory on your own (using delete or free respectively).

In the below code,

int* heapInt = new int(5);//initialize int in heap memory
.
.//use heapInt
.
delete heapInt;

Here, you will have to delete heapInt, when it is done using. If it is not deleted, then memory leakage occurs.

In order to avoid such memory leaks unique_ptr is used, where unique_ptr automatically deletes the space occupied by heapInt when it goes out of scope. So, you need not do delete or free for unique_ptr.

Solution 3

Unique pointers are guaranteed to destroy the object they manage when they go out of scope. http://en.cppreference.com/w/cpp/memory/unique_ptr

In this case:

unique_ptr<double> uptr2 (pd);

pd will be destroyed when uptr2 goes out of scope. This facilitates memory management by automatic deletion.

The case of unique_ptr<int> uptr (new int(3)); is not different, except that the raw pointer is not assigned to any variable here.

Solution 4

From cppreference, one of the std::unique_ptr constructors is

explicit unique_ptr( pointer p ) noexcept;

So to create a new std::unique_ptr is to pass a pointer to its constructor.

unique_ptr<int> uptr (new int(3));

Or it is the same as

int *int_ptr = new int(3);
std::unique_ptr<int> uptr (int_ptr);

The different is you don't have to clean up after using it. If you don't use std::unique_ptr (smart pointer), you will have to delete it like this

delete int_ptr;

when you no longer need it or it will cause a memory leak.

Share:
170,534
Roman
Author by

Roman

Updated on July 10, 2022

Comments

  • Roman
    Roman almost 2 years

    I try to understand how std::unique_ptr works and for that I found this document. The author starts from the following example:

    #include <utility>  //declarations of unique_ptr
    using std::unique_ptr;
    // default construction
    unique_ptr<int> up; //creates an empty object
    // initialize with an argument
    unique_ptr<int> uptr (new int(3));
    double *pd= new double;
    unique_ptr<double> uptr2 (pd);
    // overloaded * and ->
    *uptr2 = 23.5;
    unique_ptr<std::string> ups (new std::string("hello"));
    int len=ups->size();
    

    What is confusing to me is that in this line

    unique_ptr<int> uptr (new int(3));
    

    We use integer as an argument (between round brackets) and here

    unique_ptr<double> uptr2 (pd);
    

    we used an pointer as an argument. Does it make any difference?

    What is also not clear to me, is how pointers, declared in this way will be different from the pointers declared in a "normal" way.

    • David Schwartz
      David Schwartz almost 11 years
      new int(3) returns a pointer to the new int, just like pd was a pointer to the new double.
    • zerocukor287
      zerocukor287 about 3 years
      unique_ptr declaration is located in <memory> not in <utility>
  • Flame of udun
    Flame of udun over 7 years
    Hi, I couldn't understand anything about model object ownership, the integer leak in the code or enforcing ownership policy for object. Could you please suggest topics / resources to learn these concepts?
  • pretzlstyle
    pretzlstyle over 6 years
    I cannot use unique_ptr, without getting an error: The text ">" is unexpected. It may be that this token was intended as a template argument list terminator but the name is not known to be a template., even though I have #include <utility> and #include <memory>. Any advice?