By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,407 Members | 920 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,407 IT Pros & Developers. It's quick & easy.

C++: Uninitialised Variable Passed as a Parm

P: n/a
Is the following guaranteed safe?

void InitInt(int & SomeInt)
{
SomeInt=3;
return;
}

int main()
{
int MainInt; // not initialised!
InitInt(MainInt);
std::cout << MainInt << std::endl;
return 0;
}

The intent of the function is to initialise its parm, so why
bother initialising it first in main()? Unless, of course, it is not
safe. Is it safe?

Sincerely,

Gene Wirchenko

Jul 22 '05 #1
Share this Question
Share on Google+
22 Replies


P: n/a
On Wed, 17 Dec 2003 18:18:33 GMT, Gene Wirchenko
<gw**************@CAPITALSwencomine.com> wrote:
Is the following guaranteed safe?
Oops! I forgot to
#include <iostream>
void InitInt(int & SomeInt)
{
SomeInt=3;
return;
}

int main()
{
int MainInt; // not initialised!
InitInt(MainInt);
std::cout << MainInt << std::endl;
return 0;
}

The intent of the function is to initialise its parm, so why
bother initialising it first in main()? Unless, of course, it is not
safe. Is it safe?


Sincerely,

Gene Wirchenko

Jul 22 '05 #2

P: n/a

"Gene Wirchenko" <gw**************@CAPITALSwencomine.com> schrieb im
Newsbeitrag news:sd********************************@4ax.com...
On Wed, 17 Dec 2003 18:18:33 GMT, Gene Wirchenko
<gw**************@CAPITALSwencomine.com> wrote:
Is the following guaranteed safe?


Oops! I forgot to
#include <iostream>
void InitInt(int & SomeInt)
{
SomeInt=3;
return;
}

int main()
{
int MainInt; // not initialised!
InitInt(MainInt);
std::cout << MainInt << std::endl;
return 0;
}

The intent of the function is to initialise its parm, so why
bother initialising it first in main()? Unless, of course, it is not
safe. Is it safe?


In principle it´s safe though the practice itself is arguable - why not
initialize at the point of declaration?
To see whether it makes sense you´d need to provide some more details of
your intention.

Chris
Jul 22 '05 #3

P: n/a

"Gene Wirchenko" <gw**************@CAPITALSwencomine.com> a écrit dans le
message de news: sd********************************@4ax.com...
On Wed, 17 Dec 2003 18:18:33 GMT, Gene Wirchenko
<gw**************@CAPITALSwencomine.com> wrote:
Is the following guaranteed safe?


Oops! I forgot to
#include <iostream>
void InitInt(int & SomeInt)
{
SomeInt=3;
return;
}

int main()
{
int MainInt; // not initialised!
InitInt(MainInt);
std::cout << MainInt << std::endl;
return 0;
}

The intent of the function is to initialise its parm, so why
bother initialising it first in main()? Unless, of course, it is not
safe. Is it safe?


Sincerely,

Gene Wirchenko


sounds perfectly safe to me... nevertheless, I hardly understatnd the point
of this function : costs a function call and does almost nothing
interesting... and you don't need the return in the function InitInt.
Jul 22 '05 #4

P: n/a
On Wed, 17 Dec 2003 18:18:33 GMT, Gene Wirchenko
<gw**************@CAPITALSwencomine.com> wrote:
Is the following guaranteed safe?

void InitInt(int & SomeInt)
{
SomeInt=3;
return;
}

int main()
{
int MainInt; // not initialised!
InitInt(MainInt);
std::cout << MainInt << std::endl;
return 0;
}

The intent of the function is to initialise its parm, so why
bother initialising it first in main()? Unless, of course, it is not
safe. Is it safe?


Yes - you don't convert MainInt to an rvalue until after you've given
it a valid value.

Tom

C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Jul 22 '05 #5

P: n/a
"Le Géant Vert" <_N*****************@tiscali.fr> wrote...

"Gene Wirchenko" <gw**************@CAPITALSwencomine.com> a écrit dans le
message de news: sd********************************@4ax.com...
On Wed, 17 Dec 2003 18:18:33 GMT, Gene Wirchenko
<gw**************@CAPITALSwencomine.com> wrote:
Is the following guaranteed safe?
Oops! I forgot to
#include <iostream>
void InitInt(int & SomeInt)
{
SomeInt=3;
return;
}

int main()
{
int MainInt; // not initialised!
InitInt(MainInt);
std::cout << MainInt << std::endl;
return 0;
}

The intent of the function is to initialise its parm, so why
bother initialising it first in main()? Unless, of course, it is not
safe. Is it safe?


Sincerely,

Gene Wirchenko


sounds perfectly safe to me... nevertheless, I hardly understatnd the

point of this function : costs a function call and does almost nothing
interesting... and you don't need the return in the function InitInt.


Gene probably provided the simple function just for illustration purposes.
The point is that if you pass an uninitialised object by reference, some
compilers complain (with a warning, of course), often such warning is not
necessarily founded. That's all.

Victor
Jul 22 '05 #6

P: n/a
On Wed, 17 Dec 2003 19:39:13 +0100, "Le Géant Vert"
<_N*****************@tiscali.fr> wrote:

[snip]
sounds perfectly safe to me... nevertheless, I hardly understatnd the point
of this function : costs a function call and does almost nothing
interesting... and you don't need the return in the function InitInt.


Thank you. As to the nit:

Oh, come off it! I posted a small program that illustrated my
point. It is called an example. If the initialisation function had
included code to initialise a 79 TB structure, it would not have made
the point any better (and would probably have obscured it).

Sincerely,

Gene Wirchenko

Jul 22 '05 #7

P: n/a
On Wed, 17 Dec 2003 18:46:30 +0000, tom_usenet
<to********@hotmail.com> wrote:
On Wed, 17 Dec 2003 18:18:33 GMT, Gene Wirchenko
<gw**************@CAPITALSwencomine.com> wrote:


[snip]
The intent of the function is to initialise its parm, so why
bother initialising it first in main()? Unless, of course, it is not
safe. Is it safe?


Yes - you don't convert MainInt to an rvalue until after you've given
it a valid value.


Thank you.

Yes, very deliberately so.

(I have encountered languages where this would not be safe.)

Sincerely,

Gene Wirchenko

Jul 22 '05 #8

P: n/a
Gene Wirchenko wrote:
Is the following guaranteed safe?

void InitInt(int & SomeInt) {
SomeInt=3;
return;
}
This is poor programming practice. The following:

int InitInt(void) {
return 3;
}

would be much better.

int main(int argc, char* argv[]) {
int MainInt; // not initialized!
InitInt(MainInt);
int MainInt = InitInt();

You should *always* try to avoid uninitialized variables.
std::cout << MainInt << std::endl;
return 0;
}

The intent of the function is to initialized its parm, so why
bother initializing it first in main()? Unless, of course, it is not
safe. Is it safe?


It is *dangerous* because the variable may be used uninitialized.
If not by you, then by some poor programmer who must maintain your code.
Good programming habits will help keep you out of trouble.

Jul 22 '05 #9

P: n/a

"Gene Wirchenko" <gw**************@CAPITALSwencomine.com> wrote in message
news:dk********************************@4ax.com...
On Wed, 17 Dec 2003 19:39:13 +0100, "Le Géant Vert"
<_N*****************@tiscali.fr> wrote:

[snip]
sounds perfectly safe to me... nevertheless, I hardly understatnd the pointof this function : costs a function call and does almost nothing
interesting... and you don't need the return in the function InitInt.


Thank you. As to the nit:

Oh, come off it! I posted a small program that illustrated my
point. It is called an example.


Now I think you understand why I object when people post "answers" that are
off the topic of the original question. Interesting :-)
Jul 22 '05 #10

P: n/a
jeffc wrote:
Oh, come off it! I posted a small program that illustrated my
point. It is called an example.


Now I think you understand why I object when people post "answers" that are
off the topic of the original question. Interesting :-)


There is a difference between posting an otherwise valid program which
just demonstrates an idea and a program which contains a bug unnoticed
by the poster.

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #11

P: n/a
On Wed, 17 Dec 2003 11:24:58 -0800, "E. Robert Tisdale"
<E.**************@jpl.nasa.gov> wrote:
Gene Wirchenko wrote:
Is the following guaranteed safe?

void InitInt(int & SomeInt) {
SomeInt=3;
return;
}


This is poor programming practice. The following:

int InitInt(void) {
return 3;
}

would be much better.


No, because this is only an example of initialisation. For an
arbitrarily complex initialisation, there might be more than one parm
being initialised and in such configuration that it could not be
combined into one structure and thus would not be suitable for a
return value.
int main(int argc, char* argv[]) {
I did not write the above line. I wrote:
int main()
int MainInt; // not initialized!
InitInt(MainInt);


int MainInt = InitInt();

You should *always* try to avoid uninitialized variables.


That is why I call an initialisation routine.
std::cout << MainInt << std::endl;
return 0;
}

The intent of the function is to initialized its parm, so why
bother initializing it first in main()? Unless, of course, it is not
safe. Is it safe?


It is *dangerous* because the variable may be used uninitialized.
If not by you, then by some poor programmer who must maintain your code.
Good programming habits will help keep you out of trouble.


Initialising a variable twice is unclear. I try to avoid such
confusions. Given a complex initialisation, I would note where the
initialisation was dealt with.

Sincerely,

Gene Wirchenko

Jul 22 '05 #12

P: n/a
"E. Robert Tisdale" <E.**************@jpl.nasa.gov> wrote in message
news:3F**************@jpl.nasa.gov...
Gene Wirchenko wrote:
Is the following guaranteed safe?

void InitInt(int & SomeInt) {
SomeInt=3;
return;
}


This is poor programming practice. The following:

int InitInt(void) {
return 3;
}

would be much better.

int main(int argc, char* argv[]) {
int MainInt; // not initialized!
InitInt(MainInt);


int MainInt = InitInt();

You should *always* try to avoid uninitialized variables.
std::cout << MainInt << std::endl;
return 0;
}

The intent of the function is to initialized its parm, so why
bother initializing it first in main()? Unless, of course, it is not
safe. Is it safe?


It is *dangerous* because the variable may be used uninitialized.
If not by you, then by some poor programmer who must maintain your code.
Good programming habits will help keep you out of trouble.


The fact of the matter is that MainInt *is* initialised, albeit to a
meaningless value. What makes it bad practice is not that the initial value
of MainInt is meaningless, but rather that the initial value of MainInt is
never used. It is overwritten with a new value by InitInt(). Doesn't this
spell bad programming practice?
Jul 22 '05 #13

P: n/a
Gene Wirchenko wrote:
E. Robert Tisdale wrote:
This is poor programming practice. The following:

int InitInt(void) {
return 3;
}

would be much better.
No, because this is only an example of initialisation.
For an arbitrarily complex initialisation,
there might be more than one parameter being initialised
and in such configuration that
it could not be combined into one structure
and thus would not be suitable for a return value.
You should *always* try to avoid uninitialized variables.


That is why I call an initialisation routine.


You should avoid any initialization routine except, perhaps,
a private class member function to be called by a constructor.
A method which is applied to an object after construction
is a *modifier* and *not* an initializer.
A *modifier* changes the object's *state*.
You should try to design your classes
so that objects can be declared const
and initialized at the point where they are declared.
This minimizes the number of variables
that you need to keep track of in your program
which makes your program easier for you and other programmers
to read, understand and maintain.
Container classes are an obvious exception.
You can't do much with a const container.
Initialising a variable twice is unclear.

I try to avoid such confusions. Given a complex initialisation,
I would note where the initialisation was dealt with.


The best place to deal with [complicated] initialization
is in a constructor. Subscribers to the comp.lang.c++ newsgroup
can help you with designing constructors
to completely initialize complicated objects.

Jul 22 '05 #14

P: n/a
On Thu, 18 Dec 2003 10:55:54 +1100, "Jason Heyes"
<ja********@optusnet.com.au> wrote in alt.comp.lang.learn.c-c++:
"E. Robert Tisdale" <E.**************@jpl.nasa.gov> wrote in message
news:3F**************@jpl.nasa.gov...
Gene Wirchenko wrote:
Is the following guaranteed safe?

void InitInt(int & SomeInt) {
SomeInt=3;
return;
}
This is poor programming practice. The following:

int InitInt(void) {
return 3;
}

would be much better.

int main(int argc, char* argv[]) {
int MainInt; // not initialized!
InitInt(MainInt);


int MainInt = InitInt();

You should *always* try to avoid uninitialized variables.
std::cout << MainInt << std::endl;
return 0;
}

The intent of the function is to initialized its parm, so why
bother initializing it first in main()? Unless, of course, it is not
safe. Is it safe?


It is *dangerous* because the variable may be used uninitialized.
If not by you, then by some poor programmer who must maintain your code.
Good programming habits will help keep you out of trouble.


The fact of the matter is that MainInt *is* initialised, albeit to a


No, it is not. Not in the terms defined by the C++ standard. It is
uninitialized and might indeed contain a trap representation, that is
a bit pattern that does not represent a valid value for the object
type.
meaningless value. What makes it bad practice is not that the initial value
of MainInt is meaningless, but rather that the initial value of MainInt is
never used. It is overwritten with a new value by InitInt(). Doesn't this
spell bad programming practice?


There is no initial value to be unused. An uninitialized object has
indeterminate. Any use of an indeterminate value produces undefined
behavior.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq
Jul 22 '05 #15

P: n/a
"Jack Klein" <ja*******@spamcop.net> wrote in message
news:n9********************************@4ax.com...
On Thu, 18 Dec 2003 10:55:54 +1100, "Jason Heyes"
<ja********@optusnet.com.au> wrote in alt.comp.lang.learn.c-c++:
"E. Robert Tisdale" <E.**************@jpl.nasa.gov> wrote in message
news:3F**************@jpl.nasa.gov...
Gene Wirchenko wrote:

> Is the following guaranteed safe?
>
> void InitInt(int & SomeInt) {
> SomeInt=3;
> return;
> }

This is poor programming practice. The following:

int InitInt(void) {
return 3;
}

would be much better.

>
> int main(int argc, char* argv[]) {
> int MainInt; // not initialized!
> InitInt(MainInt);

int MainInt = InitInt();

You should *always* try to avoid uninitialized variables.

> std::cout << MainInt << std::endl;
> return 0;
> }
>
> The intent of the function is to initialized its parm, so why
> bother initializing it first in main()? Unless, of course, it is not > safe. Is it safe?

It is *dangerous* because the variable may be used uninitialized.
If not by you, then by some poor programmer who must maintain your code. Good programming habits will help keep you out of trouble.


The fact of the matter is that MainInt *is* initialised, albeit to a


No, it is not. Not in the terms defined by the C++ standard. It is
uninitialized and might indeed contain a trap representation, that is
a bit pattern that does not represent a valid value for the object
type.
meaningless value. What makes it bad practice is not that the initial value of MainInt is meaningless, but rather that the initial value of MainInt is never used. It is overwritten with a new value by InitInt(). Doesn't this spell bad programming practice?


There is no initial value to be unused. An uninitialized object has
indeterminate. Any use of an indeterminate value produces undefined
behavior.


Oh well in that case it is simply wrong code. I wasn't aware that the C++
standard was so strict with regard to initialised variables. Personally I
never declare an object without initialising it - no matter what type it is.
But let me ask you, does assigning a value to an uninitialised int result in
undefined behavior? Thanks.
Jul 22 '05 #16

P: n/a
On Thu, 18 Dec 2003 17:43:01 +1100, "Jason Heyes"
<ja********@optusnet.com.au> wrote:
No, it is not. Not in the terms defined by the C++ standard. It is
uninitialized and might indeed contain a trap representation, that is
a bit pattern that does not represent a valid value for the object
type.
> meaningless value. What makes it bad practice is not that the initialvalue > of MainInt is meaningless, but rather that the initial value of MainIntis > never used. It is overwritten with a new value by InitInt(). Doesn'tthis > spell bad programming practice?


There is no initial value to be unused. An uninitialized object has
indeterminate. Any use of an indeterminate value produces undefined
behavior.


Oh well in that case it is simply wrong code. I wasn't aware that the C++
standard was so strict with regard to initialised variables. Personally I
never declare an object without initialising it - no matter what type it is.
But let me ask you, does assigning a value to an uninitialised int result in
undefined behavior? Thanks.


No. Only using an indeterminate value as an rvalue is undefined
behaviour. Using is as an lvalue (in, say, an assignment or binding to
a reference as in the OP's code) is fine.

Tom

C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Jul 22 '05 #17

P: n/a
"tom_usenet" <to********@hotmail.com> wrote in message
news:26********************************@4ax.com...
On Thu, 18 Dec 2003 17:43:01 +1100, "Jason Heyes"
<ja********@optusnet.com.au> wrote:

Oh well in that case it is simply wrong code. I wasn't aware that the C++
standard was so strict with regard to initialised variables. Personally I
never declare an object without initialising it - no matter what type it is.But let me ask you, does assigning a value to an uninitialised int result inundefined behavior? Thanks.


No. Only using an indeterminate value as an rvalue is undefined
behaviour. Using is as an lvalue (in, say, an assignment or binding to
a reference as in the OP's code) is fine.

Tom

C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html


Cool. :)
Jul 22 '05 #18

P: n/a
In article <3f***********************@news.optusnet.com.au> ,
Jason Heyes <ja********@optusnet.com.au> wrote:
Jack Klein wrote:
> never used. It is overwritten with a new value by InitInt().
> Doesn't this spell bad programming practice?
There is no initial value to be unused. An uninitialized object has
indeterminate. Any use of an indeterminate value produces undefined
behavior.

Oh well in that case it is simply wrong code. I wasn't aware that the C++
standard was so strict with regard to initialised variables.


As is C.
Personally I
never declare an object without initialising it - no matter what type it is.
That's a very good rule of thumb, but if I'm understanding you,
forcing an initialization can often be awkward.
But let me ask you, does assigning a value to an uninitialised int result in
undefined behavior? Thanks.


No, because that's not a use of the indeterminate value.
--
Greg Comeau/4.3.3:Full C++03 core language + more Windows backends
Comeau C/C++ ONLINE ==> http://www.comeaucomputing.com/tryitout
World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries... Have you tried it?
Jul 22 '05 #19

P: n/a
Greg Comeau wrote:
Jason Heyes wrote:
Personally, I never declare an object without initializing it --
no matter what type it is.


That's a very good rule of thumb, but if I'm understanding you,
forcing an initialization can often be awkward.


Not very often
but I'll give an example where it is awkward -- containers:

int a[n];
for (int j = 0; j < n; ++j)
cin >> a[n];

Unless they are small, const containers can be awkward to initialize:

const int a[] = {0, 1, 2, 3};

Well, you get the idea. You can do this:

class wrapper {
private:
int a[n];
public:
const
int& operator[](int j) const { return a[j]; }
int& operator[](int j) { return a[j]; }
wrapper(std::istream& is) {
for (int j = 0; j < n; ++j)
is >> a[n];
}
};

then this:

const wrapper a(cin);

Of course, this can cause a problem,
if the constructor encounters an exception while reading from cin.
Is this awkward? Problematic?
I suspect that you would say yes.

Jul 22 '05 #20

P: n/a
"E. Robert Tisdale" <E.**************@jpl.nasa.gov> wrote in message
news:3F**************@jpl.nasa.gov...
Greg Comeau wrote:
Jason Heyes wrote:
Personally, I never declare an object without initializing it --
no matter what type it is.


That's a very good rule of thumb, but if I'm understanding you,
forcing an initialization can often be awkward.


Not very often
but I'll give an example where it is awkward -- containers:

int a[n];
for (int j = 0; j < n; ++j)
cin >> a[n];

Unless they are small, const containers can be awkward to initialize:

const int a[] = {0, 1, 2, 3};

Well, you get the idea. You can do this:

class wrapper {
private:
int a[n];
public:
const
int& operator[](int j) const { return a[j]; }
int& operator[](int j) { return a[j]; }
wrapper(std::istream& is) {
for (int j = 0; j < n; ++j)
is >> a[n];
}
};

then this:

const wrapper a(cin);

Of course, this can cause a problem,
if the constructor encounters an exception while reading from cin.
Is this awkward? Problematic?
I suspect that you would say yes.


To get around this you can write

std::istream &operator>>(std::istream &is, wrapper *&p)
{
int a[n];
for (int j=0; j < n; j++)
{
if (!(is >> a[j]))
return is;
}
p = new wrapper(a);
return is;
}

then

wrapper *p;
if (!(cin >> p))
// error
wrapper a = *p;
delete p;

OR you can use std::vector instead of arrays!
Jul 22 '05 #21

P: n/a
Jason Heyes wrote:

To get around this,
Please remind me what we are trying to "get around".
you can write:

std::istream &operator>>(std::istream& is, wrapper& w) {
int j = 0;
while (j < n && is >> w[j]) ++j;
return is;
}

then

wrapper* p;
if (!(std::cin >> *p)) {
/* handle error */ }
const wrapper w = *p;
delete p;
p = NULL;


But a null pointer variable p is *not* much of a safety improvement.
How about

wrapper f(std::istream& is) {
wrapper w;
is >> w;
return w;
}

then

const wrapper w = f(std::cin);
if (!cin) {
/* handle error */ }

Jul 22 '05 #22

P: n/a
E. Robert Tisdale wrote:
Jason Heyes wrote:

To get around this,

Please remind me what we are trying to "get around".
you can write:

std::istream &operator>>(std::istream& is, wrapper& w) {
int j = 0;
while (j < n && is >> w[j]) ++j;
return is;
}

then

wrapper* p;
if (!(std::cin >> *p)) {
Now, E. Robert, that is *not* what Jason wrote. He wrote:

if (!(cin >> p))

I find this distasteful, and it really doesn't solve anything. However,
I don't believe it is technically wrong.
/* handle error */ }
const wrapper w = *p;
delete p;
p = NULL;

But a null pointer variable p is *not* much of a safety improvement.


Even in your modified version, p was not (necessarily) null.

How about

wrapper f(std::istream& is) {
wrapper w;
is >> w;
return w;
}
You're throwing wrappers around as if they were candy. Keep in mind
that these are wrappers around arrays that were, by definition, too
large to initialize like this:

const int a[] = {0, 1, 2, 3};

Those copies could hurt.

then

const wrapper w = f(std::cin);
if (!cin) {
/* handle error */ }


Suppose the wrapper had to read the entire input stream, through EOF?
This code makes that an error.

Unless there's a darned good, concrete reason not to, initialize in
constructors. /Resource allocation is initialization./ EOT.

-Jeff

Jul 22 '05 #23

This discussion thread is closed

Replies have been disabled for this discussion.