I know there had been a discussion similar to this in the past but answers appear to be outdated in my opinion. Most say that the differences are the following:
Scope - since on the old questions ask with examples of these objects declared inside the method instead of as a member of the class.
Safety from memory leak - old questions use raw pointers rather than smart pointers
Given my example below, class Dog is a member of class Animal. And is using smart pointers. So the scope and memory leak are now out of the picture.
So that said.. What are the benefits of declaring a class with a pointer rather than a normal object? As basic as my example goes - without considering polymorphism, etc.
Given these examples:
//Declare as normal object class Dog { public: void bark() { std::cout << "bark!" << std::endl; } void walk() { std::cout << "walk!" << std::endl; } }; class Animal { public: Dog dog; }; int main() { auto animal = std::make_unique<Animal>(); animal->dog.bark(); animal->dog.walk(); } And..
//Declare as pointer to class class Dog { public: void bark() { std::cout << "bark!" << std::endl; } void walk() { std::cout << "walk!" << std::endl; } }; class Animal { public: Animal() { dog = std::make_unique<Dog>(); } std::unique_ptr<Dog> dog; }; int main() { auto animal = std::make_unique<Animal>(); animal->dog->bark(); animal->dog->walk(); }
Dogis never derived from then all is fine, but if there areBulldogandPoodlederived fromDogand both can be assigned toAnimal::dogthen you have to have a pointer.Dog *or astd::unique_ptr<Dog>is the ability to use polymorphism IFDogis a polymorphic base (which it isn't in your example). It is also possible to dynamically create an array ofDogwith the size determined at run time (but that array cannot contain instances of classes derived fromDog). In your case (Dognot polymorphic) neither of those benefits can be achieved, and all you have achieved is additional overhead of dynamically creating and destroying objects.