Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does unique_ptr<Derived> implicitly cast to unique_ptr<Base>?

Tags:

I wrote the following code that uses unique_ptr<Derived> where a unique_ptr<Base> is expected

class Base {     int i;  public:     Base( int i ) : i(i) {}     int getI() const { return i; } };  class Derived : public Base {     float f;  public:     Derived( int i, float f ) : Base(i), f(f) {}     float getF() const { return f; } };  void printBase( unique_ptr<Base> base ) {     cout << "f: " << base->getI() << endl; }  unique_ptr<Base> makeBase() {     return make_unique<Derived>( 2, 3.0f ); }  unique_ptr<Derived> makeDerived() {     return make_unique<Derived>( 2, 3.0f ); }  int main( int argc, char * argv [] ) {     unique_ptr<Base> base1 = makeBase();     unique_ptr<Base> base2 = makeDerived();     printBase( make_unique<Derived>( 2, 3.0f ) );      return 0; } 

and i expected this code to not compile, because according to my understanding unique_ptr<Base> and unique_ptr<Derived> are unrelated types and unique_ptr<Derived> isn't in fact derived from unique_ptr<Base> so the assignment shouldn't work.

But thanks to some magic it works, and i don't understand why, or even if it's safe to do so. Can someone explain please?

like image 396
Youda008 Avatar asked Oct 01 '19 08:10

Youda008


People also ask

What happens when you move a unique_ptr?

A unique_ptr can only be moved. This means that the ownership of the memory resource is transferred to another unique_ptr and the original unique_ptr no longer owns it. We recommend that you restrict an object to one owner, because multiple ownership adds complexity to the program logic.

Why should you use unique_ptr?

std::unique_ptr represents data which has only one owner at any given time. It should be your default choice when you need a smart pointer. You can move a std::unique_ptr around to keep it alive, but there can only be one owner of the data. After moving the pointer, the previous pointer object is invalidated.

What is the scope of unique_ptr?

An​ unique_ptr has exclusive ownership of the object it points to and ​will destroy the object when the pointer goes out of scope. A unique_ptr explicitly prevents copying of its contained pointer.

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.


1 Answers

The bit of magic you're looking for is the converting constructor #6 here:

template<class U, class E> unique_ptr(unique_ptr<U, E> &&u) noexcept; 

It enables constructing a std::unique_ptr<T> implicitly from an expiring std::unique_ptr<U> if (glossing over deleters for clarity):

unique_ptr<U, E>::pointer is implicitly convertible to pointer

Which is to say, it mimicks implicit raw pointer conversions, including derived-to-base conversions, and does what you expect™ safely (in terms of lifetime – you still need to ensure that the base type can be deleted polymorphically).

like image 180
Quentin Avatar answered Oct 12 '22 23:10

Quentin