Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pointer to unique_ptr - is this a loophole?

Tags:

c++

unique-ptr

It seems an easy way to circumvent a unique_ptr is to use a pointer to the unique_ptr object. And that's not difficult. So using the unique_ptr is sort of a gentleman's agreement and not really super enforced?

#include <iostream>
#include <memory>
using namespace std;

class Box {
  public:
    int num;
};

void update_box(unique_ptr<Box>* pu);

int main(){
  unique_ptr<Box> b{new Box};
  unique_ptr<Box>* u = &b;
  update_box(u);
  cout << b->num << endl; // Outputs 99.
  return 0;
}

void update_box(unique_ptr<Box>* pu) {
  (*pu)->num = 99;
}
like image 544
Plasty Grove Avatar asked Sep 25 '18 11:09

Plasty Grove


People also ask

Is unique_ptr a pointer?

std::unique_ptr is a smart pointer that owns and manages another object through a pointer and disposes of that object when the unique_ptr goes out of scope.

Can you copy unique_ptr?

A unique_ptr does not share its pointer. It cannot be copied to another unique_ptr , passed by value to a function, or used in any C++ Standard Library algorithm that requires copies to be made. A unique_ptr can only be moved.

Can you set unique_ptr to Nullptr?

It will work. unique_ptr& operator=(nullptr_t) noexcept ; Effects: reset() .

What is the difference between the two smart pointers shared_ptr and unique_ptr?

In short: Use unique_ptr when you want a single pointer to an object that will be reclaimed when that single pointer is destroyed. Use shared_ptr when you want multiple pointers to the same resource.


2 Answers

C++ is, in a sense, full of gentlemen's agreements. In other words, the language gives you the ability to shoot yourself in the foot.

There is nothing to prevent you taking the address of a std::unique_ptr. If you really find that distasteful then you could inherit from std::unique_ptr and overload the address-of operator with a function containing a static assertion.

But even if you did that, you could circumvent that with std::addressof!

like image 88
Bathsheba Avatar answered Sep 19 '22 13:09

Bathsheba


You actually put your real question into a comment:

My understanding of unique_ptr is that it should be used to ensure you only have one pointer to an object at any time.

No, this is wrong. You can easily do a simple:

std::unique_ptr<int> a(new int);
int *b = a.get(); // b points to the same object as a

The design of unique_ptr tries to ensure that you can only have one unique_ptr to an object. But even, it can ensure this only if you don't use naked pointers. With naked pointers, it is easy to sidestep this design:

std::unique_ptr<int> a(new int);
std::unique_ptr<int> b(a.get());

Here, b points to the same object as a, so this program has undefined behavior (because the int object will be deleted twice).

unique_ptr's intent is to show ownership. As there can be only one unique_ptr which can point to an object (ignoring the "hack" I've presented earlier), unique_ptr owns the pointed object, and as unique_ptr's destructor is called, it will delete the pointed object.

like image 28
geza Avatar answered Sep 20 '22 13:09

geza