patchwork
patchwork

Reputation: 1221

How sensible is it to put new'd objects in a constructor initialiser?

Is it sensible or silly to pass new'd objects in a constructor initialiser?

For example:

class Mallard
{
public:
  Mallard()
   : s(new SomeLargeObject(5)) {}
private:
  SomeLargeObject * s;
};

Upvotes: 3

Views: 110

Answers (3)

bobah
bobah

Reputation: 18864

There is nothing mechanically broken in your code sample if the destructor, which you forgot to publish, does the symmetric deletion.

Though conventionally (safer and less boilerplate) you'd want something like

#include <memory>

class Mallard {
    std::unique_ptr<SomeLargeObject> that_;
public:
     Mullard(): that_(new SomeLargeObject)
     {}
     // this way you don't need to code the destructor
};

Note: As people highlighted in comments (@Praetorian,@RemyLebeau,@AdrianMcCarthy), if your had been initializing more than one member this way it wouldn't have been subject to a memory leak as when an exception is thrown from the object constructor the destructor for this object is not called. The above suggested syntax with std::unique_ptr is not subject to this problem (this is why it is safe).

Upvotes: 5

Michael
Michael

Reputation: 5897

If I may throw my 2 cents:

Cent #1: Generally speaking, it would be better to make s a member of type SomeLargeObject and not concern oneself with dynamic memory allocation;

Cent #2: Sometime it is useful to allocate things in a constructor like that, and, provided that you are careful, there is nothing wrong with that. In particular, this is useful for Bridge Pattern like this:

// Abstract base of all beaks
class Beak
{
  public:
};

// Abstract base of all birds
class Bird
{
  protected: 
    const Beak *beak;

    ~Bird()
    {
        delete beak;
    }
};

class MallardBeak : public Beak
{
};

class Mallard : public Bird
{
  public:
    Mallard() : beak(new MallardBeak) { }
};

class PigeonBeak : public Beak
{
};

class Pigeon : public Bird
{
  public:
    Pigeon() : beak(new PigeonBeak) { }
};

Upvotes: 1

Nick Louloudakis
Nick Louloudakis

Reputation: 6005

Because of C++ not having a Garbage Collector (like Java, for example), you must be generally very careful on using dynamically (on heap) created objects, in general. If you miss correctly deallocating the memory that was dynamically allocated at some point, you will end up having a memory leak.

Also, on the constructor case, what if an error occurs on object creation (an exception is raised, for example) but the dynamically object is created before the exception call? Just some food for thought, you know.

Again, be very careful, and check on some techiques that protect you from such mistakes and unwanted situations like this, for example Smart Pointers, that use the RAII idiom. (Boost Libraries collection has some great implementations, giving you a variety of smart pointers you can use depending on your needs).

Upvotes: 0

Related Questions