By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
454,925 Members | 1,129 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 454,925 IT Pros & Developers. It's quick & easy.

Multiple calls to new in member initializer list okay?

P: n/a
The book "C++ Coding Standards" by Herb Sutter and Andrei Alexandrescu
warns against potential memory leaks when having multiple calls to
operator new within a single statement. (Item 13, page 25.) These
leaks would still be there when wrapping the result of each "new" in a
temporary smart pointer object.

Is there a simular risk when having multiple calls to new in member
initializer list of a constructor? For example:

class Foo
{
// I might use either std::auto_ptr or boost::scoped_ptr.
const std::auto_ptr<A> m_a;
const std::auto_ptr<B> m_b;
public:
Foo() : m_a(new A), m_b(new B) {}
};

Is the compiler allowed to do:
1. allocate memory for m_a
2. allocate memory for m_b
3. call the constructor of A
4. call the constructor of B

And then, is it allowed to leave a memory leak when the constructor of A
throws an exception?

Kind regards,

Niels Dekker
http://www.xs4all.nl/~nd/dekkerware
Jul 23 '05 #1
Share this Question
Share on Google+
1 Reply


P: n/a
Niels Dekker - no reply address wrote:
The book "C++ Coding Standards" by Herb Sutter and Andrei Alexandrescu
warns against potential memory leaks when having multiple calls to
operator new within a single statement. (Item 13, page 25.) These
leaks would still be there when wrapping the result of each "new" in a
temporary smart pointer object.

Is there a simular risk when having multiple calls to new in member
initializer list of a constructor? For example:

class Foo
{
// I might use either std::auto_ptr or boost::scoped_ptr.
const std::auto_ptr<A> m_a;
const std::auto_ptr<B> m_b;
public:
Foo() : m_a(new A), m_b(new B) {}
};

Is the compiler allowed to do:
1. allocate memory for m_a
2. allocate memory for m_b
3. call the constructor of A
4. call the constructor of B

And then, is it allowed to leave a memory leak when the constructor of A
throws an exception?

Kind regards,

Niels Dekker
http://www.xs4all.nl/~nd/dekkerware


This looks okay to me, the reason being that there is a sequence point
between "m_a(new A)" and "m_b(new B)" (that is, the first expression is
fully evaluated before the second is considered).

If the constructor of A throws an exception, "new A" will never
complete, so no memory will be leaked. If an exception is thrown after
m_a is fully constructed then the compiler will ensure that m_a is
properly destructed, so no leaks there either. The same argument
applies to B and m_b, so I would conclude that this usage is fine.

However, there is a similar usage that is not exception safe (just in
case you haven't encountered it):

Foo(std::auto_ptr a, std::auto_ptr b)
: m_a(a), m_b(b)
{}

// ...

// NOT EXCEPTION SAFE!!
Foo f(std::auto_ptr<A>(new A), std::auto_ptr<B>(new B)) ;

Here, there is NOT a sequence point between the two calls to new, so the
compiler may choose to execute "new A", then "new B", and then construct
the auto_ptr objects, but an exception thrown during "new B" would cause
the memory from "new A" to be leaked.

-Alan
Jul 23 '05 #2

This discussion thread is closed

Replies have been disabled for this discussion.