3

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?

sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • What are you trying to achieve? Mabe boxing the primitive variable in an object can help ? – clyfe Apr 06 '10 at 10:56
  • @clyfe: I don't want to have the actual value in my code since it doesn't matter. – sharptooth Apr 06 '10 at 10:57
  • I'm not sure what exactly you want. Do you want to automatically have `T obj;` default-initialize `obj` even for built-ins? That's not possible. Or do you just need a way to default-initialize `obj` no matter what type it is of? Then, as some answers already say, `T obj = T();` is the way to go. – sbi Apr 06 '10 at 11:00
  • 1
    On the other hand: `boolean variable = retrieveValue()` would not be bad either. And that's less typing :) – Matthieu M. Apr 06 '10 at 11:53
  • it seems very strange to want to initialise the variables to something but not care what. I wonder if you're trying to solve some bigger issue here and there might be a better way to approach that? – jcoder Apr 06 '10 at 12:46

5 Answers5

5

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
  • 530,221
  • 131
  • 937
  • 1,214
  • I suppose for UDTs the latter raises UB, since the ctor isn't called on raw memory, but on an already constructed object. – sbi Apr 06 '10 at 11:58
  • @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 Apr 06 '10 at 12:30
  • `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 Apr 06 '10 at 14:10
  • @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 Apr 06 '10 at 15:14
  • Indeed, at least VC9 accepts `typedef int T; T x; x.~T();`! I find this an annoying irregularity. – sbi Apr 06 '10 at 16:05
  • @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 Apr 06 '10 at 18:19
4
    int var = int();
    string str = string();
    ...

...or whatever typename you want.

Viktor Sehr
  • 12,825
  • 5
  • 58
  • 90
  • In effect, this is not different from typing int var = 0; string str; – Johan Kotlinski Apr 06 '10 at 11:04
  • 3
    @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 Apr 06 '10 at 11:13
1

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
  • 40,819
  • 6
  • 57
  • 90
0

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
  • 14,072
  • 2
  • 31
  • 53
0

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?

eemz
  • 1,183
  • 6
  • 10
  • 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 Apr 06 '10 at 11:43
  • @joefis: If you want to ask for clarification on the question use comments, not answers. – Georg Fritzsche Apr 06 '10 at 12:32
  • > 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... – eemz Apr 08 '10 at 12:52