Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Class destructor called twice when creating a shared_ptr

Tags:

c++

I'm having an issue with the class destructor being called twice when I create a shared ptr to my class.

I'm trying to create a vector of objects, and each object has a constructor and a destructor.

When I do a call such as:

std::vector<std::shared_ptr<ServoController>>  servos;
bool CreateServo(int id)
{
    std::shared_ptr<ServoController> servo = std::make_shared<ServoController>(ServoController(id));
    servos.push_back(servo);
}

The constructor for ServoController is called and then right away the Destructor for ServoController is called, before it the push_back function is even called.

Then, when I close my application, the destructor for ServoController is called again. But the constructor has only been called once so far (I only have 1 object in the vector). Shouldn't at least it make the constructor run again?

Is there any way I can make a vector of my class, and for each object in the vector, the constructor should be called once, and the destructor should be called once when the objects are removed from the vector or the vector is destroyed?

Thanks, -D

like image 452
Mich Avatar asked Dec 04 '22 23:12

Mich


1 Answers

You're creating a temporary object with this call, which is what's causing the first (unexpected) destructor call.

std::make_shared<ServoController>(ServoController(id));

The sequence of events is:

  • ServoController(id) creates a new temporary object, which is passed as an argument to std::make_shared.
  • std::make_shared<ServoController> then forwards the temporary object to ServoController's copy constructor (which probably isn't what you want). This is why your main constructor is only getting called once.
  • This creates a new object on the heap (managed by the shared_ptr) which is a copy of the temporary you created.
  • The temporary object is then immediately destroyed, which is what's calling the destructor the first time.

What you actually want is:

std::make_shared<ServoController>(id);

std::make_shared forwards its arguments directly to the constructor for its template argument. You don't need the extra constructor call in there.

like image 137
Chris Vig Avatar answered Feb 14 '23 00:02

Chris Vig