Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Smart pointers - unique_ptr for a stack-allocated variable

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;
like image 583
c0der Avatar asked Dec 21 '16 03:12

c0der


2 Answers

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.

like image 192
qxz Avatar answered Oct 15 '22 09:10

qxz


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.

like image 31
Deepak Kr Gupta Avatar answered Oct 15 '22 11:10

Deepak Kr Gupta