Channels ▼
RSS

C/C++

Calling Constructors with Placement New


Placement new

Bjarne Stroustrup, the designer of C++, explained in The Design and Evolution of C++ that his primary motivation for extending the syntax of new-expressions was to pass information about where to place the created object [3]. Hence, he dubbed the argument list after the keyword new the "placement syntax." A new-expression that includes the placement syntax is called "new with placement" or just "placement new."

The Standard C++ Library provides a placement form of operator new declared in the standard header <new> as:

void *operator new(std::size_t, void *p) throw ();

Most C++ implementations define it as an inline function:

inline
void *operator new(std::size_t, void *p) throw ()
    {
    return p;
    }

It does nothing but return the value of its second parameter. It completely ignores its first parameter. The exception-specification throw () indicates that the function isn't allowed to propagate any exceptions.

Programs can use this operator new to construct an object at a particular address. For example, if you declare the timer object as:

extern timer_type the_timer;

you can apply the constructor via the placement new-expression:

new (&the_timer) timer_type;

This placement new-expression compiles into a call to placement operator new, followed immediately by a call to the constructor:

operator new(sizeof(timer_type), &the_timer);
(&the_timer)->timer_type();

Recall that this operator new does nothing but return its second argument, and it's typically defined as an inline function. Most compilers completely eliminate the first statement during optimization.

The second statement:

(&the_timer)->timer_type();

is equivalent to:

the_timer.timer_type();

which applies the timer_type constructor to the_timer. But, again, these notations are just what I'm using to convey the concept of a constructor call. Neither one actually compiles if you try to write it yourself.

If you define the timer as a constant pointer:

timer_type *const the_timer
    = reinterpret_cast<timer_type>(0xFFFF6000);

then you can apply the constructor via the placement new-expression:

new (the_timer) timer_type;

This placement new-expression differs from the earlier ones only in that it omits the unary & (address-of) operator from the placement argument: the_timer instead of &the_timer.

The C++ Standard doesn't specify the order of implicit initialization as precisely as some programmers would like. I've heard many embedded developers express a desire for more explicit control over initialization order. Using placement new offers that control.

For example, if you have some master device that must be initialized before some slave device, just write the calls to placement new in that order within some larger initialization function, as in:

void initialize()
    {
    new (&the_master) master_type;
    new (&the_slave) slave_type;
    }

Still Room for Improvement

C++ programmers expect classes to use constructors to perform object initialization. Classes for memory-mapped devices should be no different. However, many common declarations for such objects don't invoke constructors implicitly. Placement new offers a way to invoke constructors explicitly, which might be what you want sometimes, but not necessarily always. At other times, implicit initialization might still be preferable. I'll be looking at other more flexible alternatives in the future.

References

  1. Saks, Dan. "Throw and catch," ESD, May, 2007.
  2. Saks, Dan. "Function Name Overloading," Embedded Systems Programming, May 1999.
  3. Bjarne Stroustrup. The Design and Evolution of C++. Addison-Wesley, 1994.


Dan Saks is president of Saks & Associates, a C/C++ training and consulting company. For more information about Dan Saks, visit his website at www.dansaks.com. This article is adapted from an article that appeared in 2011 in EE Times.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video