views:

174

answers:

5

How do I default-initialize a local variable of primitive type in C++? For example if a have a typedef:

typedef unsigned char boolean;//that's Microsoft RPC runtime typedef

I'd like to change the following line:

boolean variable = 0; //initialize to some value to ensure reproduceable behavior
retrieveValue( &variable ); // do actual job

into something that would automagically default-initialize the variable - I don't need to assign a specific value to it, but instead I only need it to be intialized to the same value each time the program runs - the same stuff as with a constructor initializer list where I can have:

struct Struct {
   int Value;
   Struct() : Value() {}
};

and the Struct::Value will be default-initialized to the same value every time an instance is cinstructed, but I never write the actual value in the code.

How can I get the same behavior for local variables?

+4  A: 
    int var = int();
    string str = string();
    ...

...or whatever typename you want.

Viktor Sehr
In effect, this is not different from typing int var = 0; string str;
kotlinski
...and it's more typing, and less readable.
kotlinski
@kotlinski: yes but’s *interchangeable*. It works with every typename without the need to change the literal. Of course, for such code as the above this makes little sense. It makes more sense when used in conjunction with templates, however.
Konrad Rudolph
OK, I get it, thanks.
kotlinski
+4  A: 

You can emulate that behaviour by the following:

boolean x = boolean();

or, more general,

T x = T();

This will default-initialize x if such a default-initialization exists. However, just writing T x will never do the trick for local variables, no matter what you do.

You can also use placement-new to invoke a “constructor”, even for POD:

T x;
new (&x) T();

Notice that this code produces undefined behaviour for non-POD types (in particular for types that have a non-trivial destructor). To make this code work with user-defined types, we first need to call the object’s destructor:

T x;
x.~T();
new (&x) T();

This syntax can also be used for PODs (guaranteed by §§5.2.4/12.4.15) so the above code can be used indiscriminately for any type.

Konrad Rudolph
I suppose for UDTs the latter raises UB, since the ctor isn't called on raw memory, but on an already constructed object.
sbi
@sbi: true: for UDTs the latter *must* first call the destructor. I was only talking about PODs but I’ll clarify this to prevent misunderstandings.
Konrad Rudolph
`x.~T();` indeed works in a template, where `T` is `int`. However, writing the same literally (`x~int();`) fails with both VC9 and Comeau.
sbi
@sbi: so does GCC 4.4.2 with `-pedantic`. The grammar at §5.2 mentions that a `type-name` is valid here and this means `class-name`, `enum-name` or `typedef-name`. So fundamental types are indeed not allowed here – but typedefs to them *are*.
Konrad Rudolph
Indeed, at least VC9 accepts `typedef int T; T x; x.~T();`! I find this an annoying irregularity.
sbi
@sbi: That’s built-in types for you. Similar exceptions apply to built-in types consisting of two (or more) lexemes. For example, try “default-constructing” an `unsigned int` (`unsigned` alone works fine, of course).
Konrad Rudolph
A: 

Wrapping in the struct (Boolean) as in your example and accessing via a public member (Boolean::value). It may not be the most elegant solution (some cruft for small benefit), but it similar to what you already showed.

stefaanv
+1  A: 

You could provide a wrapper that behaves as the underlying type through overloaded conversion operators.

#include <cassert>

template <class T>
class Type
{
    T t;
public:
    Type(const T& t = T()): t(t) {}
    operator T&() { return t; }
    operator const T&() const { return t; }
};

int main()
{
    Type<unsigned char> some_value;
    assert(some_value == '\0');
}

This should be a rather OK usage for conversion operators.

UncleBens
A: 

If I understand the original question, the poster is saying he wants variables of a given type to always have the same initial value, but he doesn't care what that value is, because he'll never look at it. Am I right?

If so, then my question for the poster is this: If you did not initialize the variables they would have random initial values... but you said you never look at initial values - so why does it matter if they're random?

I think the key question is - what are you trying to achieve here?

joefis
Uninitialized variables can introduce non-reproduceable behavior. The same variable might have different values on different program runs. That's what I don't want.
sharptooth
@joefis: If you want to ask for clarification on the question use comments, not answers.
Georg Fritzsche
> The same variable might have different values> on different program runs.OK, but that's only relevant if you access and use the values of uninitialized variables, which is a bug surely...
joefis