22

I'm currently working on some quite old C++ code and often find things like

int i;
i = 42;

or

Object* someObject = NULL;
someObject = new Object();

or even

Object someObject;
someObject = getTheObject();

I completely understand what this code does but I really have no idea when such a separation of variable definition and initialization could be helpful. I searched for some explanations but always ended up with member initialization lists or the question when you should define your local variables.

In the end, I don't understand the reason why someone could have intentionally written this code. It just splits definition and initialization up into two subsequent lines and creates overhead – in the last case it creates an object using the default constructor only to destroy it in the next line.

I wonder whether I should simply change the code to

int i = 42;
Object* someObject = new Object();
Object someObject = getTheObject();

Could this lead to any problems?

sth
  • 222,467
  • 53
  • 283
  • 367
Baldewin
  • 1,613
  • 2
  • 16
  • 23
  • 7
    Might be written by someone with ANSI C background. – Šimon Tóth Mar 23 '11 at 10:55
  • 1
    Yeah, definitely looks like something influenced by C. Basically, there you define all your local variables at the beginning of the function, and only later use them, allocate memory to your pointers etc. If only a single local variable is used, that would lead to those two-line combinations you observe. – Mephane Mar 23 '11 at 13:36

8 Answers8

16
Object someObject;
someObject = getTheObject();

This uses the assignment operator.

Object someObject = getTheObject();

This uses the copy constructor.

Apart from that, your suggested changes are equivalent, and you should implement them. The copy ctor/assignment operator difference is expected to produce the same result, this is not enforced by the language though.

I see no valid reason to split up declaration and assignment like the original code does - even though for all practical purposes it doesn't introduce overhead (except for the object)

Erik
  • 88,732
  • 13
  • 198
  • 189
  • @Erik : You are on fire these days. 11k rep in no time. Great going. :) – Prasoon Saurav Mar 23 '11 at 11:11
  • 1
    The first version also use the default constructor to initialise someObject before the assignment. – Tobias Mar 23 '11 at 11:13
  • Thanks for the explanation. I did not know that `Object someObject = getTheObject();` calls the copy constructor. I thought only `Object someObject( getTheObject() );` would call the copy constructor. – Baldewin Mar 23 '11 at 11:19
  • 1
    @Tobias : Not necessarily. The temporary in most cases gets optimized. – Prasoon Saurav Mar 23 '11 at 11:19
  • @Prasoon Saurav: Yes the compiler may be able to remove the usage of default constructor. If the intent is to initialise someObject using getTheObject the code should reflect that intent. The first solution also forces Object to have a public default constructor. – Tobias Mar 23 '11 at 11:47
  • @Prasoon: isn't it great to see new interesting users :D ? – Matthieu M. Mar 23 '11 at 12:28
  • @Matthieu : Yeah thats what I like about SO. So many intelligent users fighting(not literally) among themselves to give better answers. :) – Prasoon Saurav Mar 23 '11 at 12:30
8

In C, there is the restriction that you have to define your variables at the top of the code block, even if you only need them somewhere later on in the function. So in the old days of C, people often first defined all their variables and then later though about the values they should have.

Since you say it is quite old C++ code, it might use that same convention as a holdover from C practices.

There is no real reason to do this in C++, though. Better always define your variables where you can initialize them directly.

sth
  • 222,467
  • 53
  • 283
  • 367
  • Yes, I'm aware of this C restriction. But definition and assignment really are done in two subsequent lines! – Baldewin Mar 23 '11 at 11:20
  • I agree using one line is normally better, and you might as well change it. However, I occasionally find the C way simpler: if (whether it's a good idea or not) I reuse a variable (say, a loop variable, because it's easier to read several 1-10 loops all using ii than trying to give them different indices), then it's often clearer to declare it first, and initialize it at the start of each loop or block of code that uses it. In whcih case the first may be immediately after the declaration, but maybe better for that to match the others. – Jack V. Mar 23 '11 at 12:29
6

The change you propose is highly recommended! This is part of an important idiom in C++ programming, namely Resource Acquisition Is Initialization.

Björn Pollex
  • 75,346
  • 28
  • 201
  • 283
2

There is a good technical reason on ROM-based hardware, it is NOT a style issue:

On ROM/EEPROM based embedded systems, this has an effect on where in the binary the value is written. Uninitialized variables are written into .bss, whereas initialized variables are written into .data. Premature initialization will bloat your ROM space, which on older embedded systems can get you into big, big trouble. If you are running on a system with a small ROM, you can run out of memory if you initialize needlessly. Some goofy compilers will even address directly into the ROM, making these values effectively read-only if you are not careful.

e.g. See this GameBoy example for a more thorough explanation: http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_varinit

Lisa
  • 439
  • 2
  • 8
2

Consider the following case:

SomeType object;
if( whateverCondition ) {
   object = getObjectOneWay();
} else {
   object = getObjectAnotherWay();
}

this way it's clear that both branches assign the variable and its initial value is irrelevant. It's rarely worth that however.

sharptooth
  • 167,383
  • 100
  • 513
  • 979
2

Why separate variable definition and initialization in C++?

You haven't separated definition and initialization. You have just assigned the variable/object (to some particular) value in your code snippet. So the title is misleading.

Object someObject;
someObject = getTheObject();

is quite different from Object someObject = getTheObject();

someObject = getTheObject(); invokes the assignment operator of Object class whereas in Object someObject = getTheObject(); copy constructor of the class gets invoked. This is also known by the name copy initialization

A good compiler might generate the same code in case of int i; i = 42; and int i =42. There won't be much of an overhead.

BTW I always prefer int i = 42 to int i; i=42 and

Object someObject = getTheObject(); to

Object someObject; someObject = getTheObject();

P.S : int i = 42 defines and initializes i whereas int i; i=42 defines i and then assigns 42 to it.

Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
1
int i;
i = 42;

That is not separate variable definition and initialization.

That is separate variable declaration and assignment. I don't see any reason for this. If you know the value at the time of declaration of variable, then initialize it right then. So your question doesn't has any rationale explanation.

Of course, if you don't know the value at the time of declaration, then you don't have any choice, you need assignment then.

Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • 1
    Agree, but where is the answer? – CharlesB Mar 23 '11 at 10:54
  • @Baldewin: I think I answered (or rather opined) that * I don't see any reason for this*. And also added that *If you know the value at the time of declaration of variable, then initialize it right then!*. – Nawaz Mar 23 '11 at 10:57
  • @Nawaz : `int i` is not just a declaration but also a definition. – Prasoon Saurav Mar 23 '11 at 11:06
  • @Prasoon: I think, in C, there is something called "tentative defintion" which is not as such "definition". – Nawaz Mar 23 '11 at 11:09
  • @Nawaz : What I meant was in OP's code `int i` is not just a declaration but also a definition. Tentative definition is different and has nothing to do with the code provided by OP. – Prasoon Saurav Mar 23 '11 at 11:11
0

No. It's a matter of style.

However if he ever wanted to move the declaration out of the function it would be less editing if the declaration and initialization is seperated.

orlp
  • 112,504
  • 36
  • 218
  • 315