30

I'm writing a template class and at one point in my code would like to be able to value-initialize an object of the parameterized type on the stack. Right now, I'm accomplishing this by writing something to this effect:

template <typename T> void MyClass<T>::doSomething() { T valueInitialized = T(); /* ... */ } 

This code works, but (unless the compiler is smart) it requires an unnecessary creation and destruction of the temporary T object. What I'd like to write is the following, which I know is incorrect:

template <typename T> void MyClass<T>::doSomething() { T valueInitialized(); // WRONG: This is a prototype! /* ... */ } 

My question is whether there is a nice way to value-initialize the automatic object without having to explicitly construct a temporary object and assign it over to the automatic object. Can this be done? Or is T var = T(); as good as it gets?

4
  • Good question. :) (Though you should know better than to thank in a question body!) Commented Jun 9, 2011 at 19:18
  • Out of curiosity, why is this a concern? If T is a user-defined type, it should have a default constructor. If it's an intrinsic type, the performance loss from copy-constructing should be negligible. Even that's assuming that the compiler won't optimize it away. Commented Jun 9, 2011 at 19:21
  • @Maxpm- This is mostly out of curiosity. I've always used the T var = T(); syntax and figured that there was probably a cleaner way to do it. You're completely correct that the performance hit should be negligible. Commented Jun 9, 2011 at 19:23
  • Also related: stackoverflow.com/questions/2671532/… Commented Feb 19, 2012 at 4:56

3 Answers 3

24

The following uses copy-initialization, which is 'probably fine' 95% of the time in C++03:

T var = T(); 

But for generic (C++03) code, you should always prefer direct-initialization to account for that other 5%:

T var((T())); // extra parentheses avoid the most vexing parse – the extra parentheses // force the contents to be evaluated as an expression, thus implicitly // *not* as a declaration. 

Or better yet, use the Boost.Utility.ValueInit library, which packages up the ideal behavior for you along with workarounds for various compiler deficiencies (sadly, more than one might think):

boost::value_initialized<T> var; 

For C++11, one can use list-initialization syntax to achieve direct value-initialization in a significantly less noisy/ugly manner:

T var{}; // unambiguously value-initialization† 

(N.b. technically this will invoke std::initializer_list<> constructors instead of performing value-initialization for certain pathological types. Presumably the net result should be the same.)

Sign up to request clarification or add additional context in comments.

7 Comments

Ugh, that looks like LISP. :) Does this really work with all types? +1 from me for suggesting a boost library.
Yes, it works with all types. The parentheses are benign but disambiguate the declaration.
Unless I'm misinterpreting the difference between direct- and copy-initialization, this only makes a difference in whether conversion constructors are permitted, not in whether a temporary object is created. Is this correct? If so, what advantage does this particular approach offer over the copy-initialized version?
This doesn't work with all types after all. Specifically, it doesn't work with non-copyable/non-moveable types. Happily, the Boost library does.
I didn't know the Most Vexing Parse surrendered if you threw enough parentheses at it.
|
16

You can use curly braces in C++0x:

T valueInitialized{}; 

1 Comment

Ah, I hadn't thought of C++11! +1 from me!
5

No, there isn't any other way to reliably value-initialize a template type in C++03.

If you can count on T only being class types with default constructors, you could just write

T valueInitialized; 

but if T might as well be a built-in type,

T valueInitialized = T(); 

is the way to go.

Do you have any reason to not to trust your compiler to optimize away that copy?

1 Comment

Oh, I absolutely trust the compiler to do it. :-) This is mostly a question about whether there's a more elegant way to do this that doesn't rely on a smart compiler author.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.