I have a function that creates a unique pointer to a dynamically allocated object "c".
template<typename T, typename... TArgs> void addComponent(TArgs&&... MArgs) {
if(!components.count(typeid(T))) {
T* c = new T(std::forward<TArgs>(MArgs)...);
c->entity = this;
std::unique_ptr<Component> uPtr{ c };
components[typeid(T)] = (std::move(uPtr));
c->init();
}
}
My understanding is that the unique_ptr takes control of the value of c because you can't have another pointer pointing too a unique_ptr, however c->init still works after c has been turned into a unique_ptr.
Why does this work? Does c somehow still point to the same new T() or is an entirely new object created?
CodePudding user response:
No new objects are created and nothing takes control over anything. You wrapped the raw pointer with the smart pointer, and should not use the raw pointer anymore.
The smart pointers only work if you don't work around them by using the raw pointer. But the value of the variable c doesn't change because of the assignment operator in std::unique_ptr constructor. It remains the same, and you as the programmer should be disciplined about not using it directly any more.
Good practice would be to have it as a temporary variable that disappears after it's wrapped into a smart pointer; or instead of new just use std::make_unique.
CodePudding user response:
The unique_ptr object stores a copy of the value of c. When the unique_ptr object is destroyed, its destructor will call delete on the stored pointer value.
The original variable c is not modified by the unique_ptr, and continues to point to the same object. It is perfectly fine to dereference it. The important thing is that since this pointer value will be deleted automatically by the unique_ptr, (1) you must not continue using its value after the unique_ptr's lifetime expires, and (2) you must not try to delete it manually.
