Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

If I take a raw pointer of a unique_ptr and then use reset, is the raw pointer still guaranteed to be valid?

Tags:

c++

unique-ptr

Eg I'm pretty sure this works.

int foo = 51;
int* bar = &foo;
foo = 3;

So bar is still valid, and *bar == 3.

What about if we say

std::unique_ptr<int> foo(new int(51));  // should probably use make_unique
int* bar = foo.get();
foo.reset(new int(3));

Am I guaranteed that *bar == 3? Or am I causing undefined behavior by continuing to reference bar?

like image 347
wrhall Avatar asked May 13 '15 20:05

wrhall


People also ask

What does unique_ptr reset method do?

unique_ptr::resetReplaces the managed object. 1) Given current_ptr , the pointer that was managed by *this, performs the following actions, in this order: Saves a copy of the current pointer old_ptr = current_ptr. Overwrites the current pointer with the argument current_ptr = ptr.

What happens to unique_ptr after move?

"Moving" transfers ownership to a new unique_ptr and resets the old unique_ptr .

Does unique_ptr delete automatically?

That is, you should know that a unique_ptr will safely delete its underlying raw pointer once it goes out of scope.

What is the key advantage of a smart pointer over raw pointers?

One of the advantages of smart pointers is, that they ensure due to RAII, that the actual object is deleted. When using a raw pointer, you need to have a delete for every possible exit point, and still an exception will lead to a memory leak. Smart pointers will also free the memory if an exception occurs.


1 Answers

No, not at all. You will get undefined behaviour, as the raw pointer managed by the unique_ptr is changed by the reset. In fact, the unique_ptr deletes the managed pointer and reallocates a new one, so your old pointer will keep pointing to the old address, which is no longer valid. Your code is equivalent to this:

#include <iostream>

int main()
{
    int* managed = new int(51); // equivalent to unique_ptr(new int(51));
    int* bar = managed; // equivalent of unique_ptr::get
    delete managed; managed = new int(3); // equivalent to unique_ptr::reset(new int(3))
    std::cout << *bar << std::endl; // Wrong!!! Undefined behaviour, bar is dangling!
}

Your first code snippet is indeed correct, since you are not changing any address there, you are just changing the variable the pointer points to, so of course dereferencing the pointer will get you the updated value.

like image 55
vsoftco Avatar answered Nov 08 '22 09:11

vsoftco