Smart pointers - unique_ptr for a stack-allocated variable

11.2k Views Asked by At

I have the following simple code, and I have not found a thread where smart pointers are used for this simple case, but rather copy objects:

int main()
{
    int i = 1;

    std::unique_ptr<int> p1(&i);
    *p1 = 2;

    return 0;
}

This results in _BLOCK_TYPE_IS_INVALID when the pointer goes out of scope. If I call p1.release(), the code works fine and I do not get this error. I thought such pointers are smart enough to handle dangling pointers?

An alternative would be if I had a copy of i, which does not give the above error:

std::unique_ptr<int> p1(new int(i));

What is the advantage of using smart pointers here, where I do not want to perform the local copy?

If I were to use a raw pointer:

int i = 1;
int *p1 = &i;
*p1 = 2;

I would not get an error, even if I don't code:

p1 = nullptr;
2

There are 2 best solutions below

1
On

The answer provided by @qzx is the main reason of the problem you've reported in your code

One additional thing about std::unique_ptr<> usage. You should always try to use std::make_unique<>() to create a std::unique_ptr. It sometimes help in using this pointer appropriately by providing appropriate compilation errors.

For example, if you change the above code with std::make_unique<> as

int i = 1;
std::unique_ptr<int> p1 = make_unique<int>(&i);

then most compiler will give error as

can't convert int* to int

It will help you to use a copy which creates a totally new integer whose ownership is taken by std::unique_ptr<>

int i = 1;
std::unique_ptr<int> p1 = make_unique<int>(i);
*p1 = 2;

This code works.

3
On

std::unique_ptrs are for handling dynamically allocated memory; they're said to take ownership of the pointer when you construct one.

Your int i; is on the stack, and thus isn't dynamically allocated; it's ownership can't be taken away from the stack. When the unique_ptr destructor tries to delete the pointer you gave it (because it thinks nobody owns it anymore), you get that error because delete can only be used for pointers created with new.

Given your short example, I don't know what context this is in... But you should use raw pointers (or make a copy, as you said) for stack-allocated variables.