 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
monade@gmail.com Guest
|
Posted: Tue Jun 07, 2005 9:55 am Post subject: uninitialized variables |
|
|
I've learned to always initialize variables on declaration, so version
2 should be prefered to version 1 in this code sample:
using namespace boost;
tuple< int, double > getValues()
{
return make_tuple( 37, 3.14 );
}
void main()
{
// version 1
int i; double d;
tie( i, d ) = getValues();
//
// version 2
tuple< int, double > t = getValues();
int& i2 = t.get<0>();
double& d2 = t.get<1>();
//
}
But somehow version 1 looks smarter. Which one is better?
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Robert Kindred Guest
|
Posted: Tue Jun 07, 2005 1:59 pm Post subject: Re: uninitialized variables |
|
|
<monade (AT) gmail (DOT) com> wrote
| Quote: | I've learned to always initialize variables on declaration, so version
2 should be prefered to version 1 in this code sample:
[]
// version 2
tuple< int, double > t = getValues();
int& i2 = t.get<0>();
double& d2 = t.get<1>();
//
}
But somehow version 1 looks smarter. Which one is better?
|
I believe that in the above, if an object has a default constructor, then
each line will invoke two actions; first the default constructor, then the
assignment operator. It might be better to do the following:
| Quote: | // version 2
tuple< int, double > t(getValues());
int& i2(t.get<0>());
double& d2(t.get<1>());
//
}
|
So that one constructor takes care of each line.
hth, Robert Kindred
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
James Daughtry Guest
|
Posted: Tue Jun 07, 2005 10:48 pm Post subject: Re: uninitialized variables |
|
|
| Quote: | I've learned to always initialize variables on declaration
You've misinterpreted the rule of thumb that all variables should be |
initialized before use. That can be done through explicit
initialization at definition time, initialization through assignment
just before use, or initialization through input. Version 1 is
performing the second of those options, so it still follows the rule,
and it also happens to be cleaner.
| Quote: | void main()
main returns int |
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Pete Becker Guest
|
Posted: Tue Jun 07, 2005 10:51 pm Post subject: Re: uninitialized variables |
|
|
[email]monade (AT) gmail (DOT) com[/email] wrote:
| Quote: | I've learned to always initialize variables on declaration, so version
2 should be prefered to version 1 in this code sample:
using namespace boost;
tuple< int, double > getValues()
{
return make_tuple( 37, 3.14 );
}
void main()
{
// version 1
int i; double d;
tie( i, d ) = getValues();
//
// version 2
tuple< int, double > t = getValues();
int& i2 = t.get<0>();
double& d2 = t.get<1>();
//
}
But somehow version 1 looks smarter. Which one is better?
|
They do two different things, so the one that's better is the one that
does what you want to do. If you need to initialize references then the
second one is the only way. If you need to initialize values then either
approach works. In that case the first is clearer and just as efficient,
so it's obviously the way to go.
--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Francis Glassborow Guest
|
Posted: Wed Jun 08, 2005 8:00 am Post subject: Re: uninitialized variables |
|
|
In article <11ab79qgtkku0bd (AT) corp (DOT) supernews.com>, Robert Kindred
<RKindred (AT) SwRI (DOT) edu> writes
| Quote: | monade (AT) gmail (DOT) com> wrote in message
news:1118133623.111404.259410 (AT) g14g2000cwa (DOT) googlegroups.com...
I've learned to always initialize variables on declaration, so version
2 should be prefered to version 1 in this code sample:
[]
// version 2
tuple< int, double > t = getValues();
int& i2 = t.get<0>();
double& d2 = t.get<1>();
//
}
But somehow version 1 looks smarter. Which one is better?
I believe that in the above, if an object has a default constructor, then
each line will invoke two actions; first the default constructor, then the
assignment operator. It might be better to do the following:
|
Then you are, I think, mistaken. An '=' in a declaration statement is
not an assignment operator.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
monade@gmail.com Guest
|
Posted: Wed Jun 08, 2005 12:14 pm Post subject: Re: uninitialized variables |
|
|
I was just wondering how strict item 19 in "C++ Coding Standards" by
H.S. and A.A. was meant to always initialize variables upon definition.
In Example 2 it says:
| Quote: | // Not recommended, uninitialized
int var;
if (condition) {
// ...code...
var = someValue;
} else {
// ...code...
var = someOtherValue;
}
// better, initialized
int var = ComputeVar();
|
I agree to that if you have the choice but its difficult to achieve if
you have several variables to intialize at once. I think to initalize a
tuple (and to define convenience references) in Version 2 is the
literal translation of this sample, but version 1 is a nice and safe
compromise.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Robert Kindred Guest
|
Posted: Thu Jun 09, 2005 9:44 am Post subject: Re: uninitialized variables |
|
|
"Francis Glassborow" <francis (AT) robinton (DOT) demon.co.uk> wrote
| Quote: | In article <11ab79qgtkku0bd (AT) corp (DOT) supernews.com>, Robert Kindred
[email]RKindred (AT) SwRI (DOT) edu[/email]> writes
[email]monade (AT) gmail (DOT) com[/email]> wrote in message
news:1118133623.111404.259410 (AT) g14g2000cwa (DOT) googlegroups.com...
[]
I believe that in the above, if an object has a default constructor, then
each line will invoke two actions; first the default constructor, then
the
assignment operator. It might be better to do the following:
Then you are, I think, mistaken. An '=' in a declaration statement is
not an assignment operator.
|
Well, OK, what is it then? I know that a struct can have an '='
initializer, as well as a class that is entirely public. What about classes
that have private data?
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
James Daughtry Guest
|
Posted: Thu Jun 09, 2005 9:48 am Post subject: Re: uninitialized variables |
|
|
| Quote: | I was just wondering how strict item 19 in "C++ Coding Standards" by
H.S. and A.A. was meant to always initialize variables upon definition.
As with any style guideline, you have to use your brain when you employ |
it. Blind adherance to 'always do this' or 'never do that' can cause
problems, while understanding the guideline and using it where
appropriate is more likely to save you trouble. Consider the quoted
example:
| Quote: | // Not recommended, uninitialized
int var;
if (condition) {
// ...code...
var = someValue;
} else {
// ...code...
var = someOtherValue;
}
// better, initialized
int var = ComputeVar();
|
And how would you plan on turning the if statement into ComputeVar()?
Sure, you could do this:
int ComputeVar()
{
if (condition) {
// ...code...
return someValue;
} else {
// ...code...
return someOtherValue;
}
}
But what if condition relies on a local variable? You could pass it as
an argument:
int ComputeVar(bool condition)
{
if (condition) {
return someValue;
} else {
return someOtherValue;
}
}
int var = ComputeVar(/* condition with local variable */);
That's all well and good, but what if instead of an if..else, you have
a long chain of else if's too? What if the ...code... parts all rely on
local variables of the calling function? Generalizing this technique
robustly is difficult, and you'll most likely end up with bloated code
just to avoid a single uninitialized variable. Do you think it's worth
the effort? In some cases, yea, it would be. In most cases, probably
not.
In the end, the best advice is to use whatever most clearly shows your
intentions. If that means having an uninitialized variable floating
around until you need it, at which point you initialize it before use,
then so be it. If you can get away with initializing all of your
variables without having to jump through hoops to do it, more power to
you. Otherwise, use your brain and your own judgement about when to
apply style guidelines.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Francis Glassborow Guest
|
Posted: Thu Jun 09, 2005 12:40 pm Post subject: Re: uninitialized variables |
|
|
In article <11aduu866ec8ke4 (AT) corp (DOT) supernews.com>, Robert Kindred
<RKindred (AT) SwRI (DOT) edu> writes
| Quote: | Then you are, I think, mistaken. An '=' in a declaration statement is
not an assignment operator.
Well, OK, what is it then? I know that a struct can have an '='
initializer, as well as a class that is entirely public. What about classes
that have private data?
|
In declaration statements an '=' is one of several forms for the
initialisation syntax. It is only valid when the expression on the right
is either of the type of the name being declared on the left or is
implicitly convertible into that type. If the types match initially the
syntax is largely equivalent to calling a copy constructor:
mytype mt = expr;
is generally equivalent to:
mytype mt(expr);
if expr is an expression of type mytype. I say generally because there
are some awkward corner cases in initialisation syntax which leads me to
be wary of stating it as universally true.
However, if the type of expr is not mytype but only convertible to a
mytype via a suitable constructor
mytype mt = expr;
is equivalent to
mytype mt(mytype(expr));
and the compiler is explicitly allowed to suppress the copy constructor
and directly construct mt from expr.
However mt(expr) and mt = expr need not be equivalent. There are some
unfortunate corner cases where it matters that the inner constructor
call has been made explicit.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Thu Jun 09, 2005 12:46 pm Post subject: Re: uninitialized variables |
|
|
Robert Kindred wrote:
| Quote: | "Francis Glassborow" <francis (AT) robinton (DOT) demon.co.uk> wrote in message
news:u4KUwlUirbpCFwsI (AT) robinton (DOT) demon.co.uk...
In article <11ab79qgtkku0bd (AT) corp (DOT) supernews.com>, Robert Kindred
[email]RKindred (AT) SwRI (DOT) edu[/email]> writes
[email]monade (AT) gmail (DOT) com[/email]> wrote in message
news:1118133623.111404.259410 (AT) g14g2000cwa (DOT) googlegroups.com...
[]
I believe that in the above, if an object has a default
constructor, then each line will invoke two actions; first
the default constructor, then the assignment operator. It
might be better to do the following:
Then you are, I think, mistaken. An '=' in a declaration
statement is not an assignment operator.
Well, OK, what is it then?
|
Just part of the declaration syntax. There are two types of
initialization:
Type var( param ) ; // Direct initialization...
Type var = param ; // Copy initialization...
Formally, the first calls the Type constructor directly with the
parameter (or parameters), the second converts the parameters to
Type var, and calls the copy constructor. In the second, the
compiler is generally permitted to optimize the additional copy
away, but it can only do so if the code is otherwise legal,
i.e. the copy constructor is accessible.
If the = sign is followed by a {, the type must be an
agglomerate (e.g. no user defined constructors); copy
construction is invoked for each initialized member of the
agglomerate, for initialized members, the equivalent of Type()
is copied.
Note that if you have overloaded operator=, it won't get called
here, since the = token is not an operator in this context. And
if you declare the copy constructor private, the code will fail
to compile, even if you provide an accessible operator=.
| Quote: | I know that a struct can have an '=' initializer, as well as a
class that is entirely public. What about classes that have
private data?
|
Any class which has an accessible copy constructor. (The
compiler generated default copy constructor is public.)
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Pete Becker Guest
|
Posted: Fri Jun 10, 2005 10:17 am Post subject: Re: uninitialized variables |
|
|
James Daughtry wrote:
| Quote: |
And how would you plan on turning the if statement into ComputeVar()?
Sure, you could do this:
int ComputeVar()
{
if (condition) {
// ...code...
return someValue;
} else {
// ...code...
return someOtherValue;
}
}
|
That would conflict with another common guideline, that a function
should have only one return statement. <g>
--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
monade@gmail.com Guest
|
Posted: Fri Jun 10, 2005 4:35 pm Post subject: Re: uninitialized variables |
|
|
Isn't this "single-return-guideline" obsolet? In the face of exceptions
you have to deal with premature function-exits anyway.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Dave Harris Guest
|
Posted: Sun Jun 12, 2005 3:34 pm Post subject: Re: uninitialized variables |
|
|
[email]mordock32 (AT) hotmail (DOT) com[/email] (James Daughtry) wrote (abridged):
| Quote: | That's all well and good, but what if instead of an if..else, you have
a long chain of else if's too? What if the ...code... parts all rely on
local variables of the calling function?
|
If there are too many local variables to pass, the function using them is
probably rather long and complex, so you should consider refactoring it
anyway. One approach is to turn the stack frame into an object, so that
the local variables become instance variables and the function becomes a
member function. Then you don't need to pass the arguments around any
more; you can access them via the implicit "this".
A google search on "method object" will turn up more details.
-- Dave Harris, Nottingham, UK.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Dave Harris Guest
|
Posted: Sun Jun 12, 2005 3:34 pm Post subject: Re: uninitialized variables |
|
|
[email]monade (AT) gmail (DOT) com[/email] () wrote (abridged):
| Quote: | I agree to that if you have the choice but its difficult to achieve if
you have several variables to intialize at once. I think to initalize a
tuple (and to define convenience references) in Version 2 is the
literal translation of this sample, but version 1 is a nice and safe
compromise.
|
I've not read the book, but one approach is to move the subsequent code
into a new function and make the local variables arguments of that
function. So:
void do_something( bool condition ) {
int x, y;
if (condition) {
x = 1;
y = 42;
}
else {
x = 37;
y = -99;
}
// use x and y.
}
becomes:
void do_something( bool condition ) {
if (condition)
do_something_with_x_y( 1, 42 );
else
do_something_with_x_y( 37, -99 );
}
void do_something_with_x_y( int x, int y ) {
// Use x and y.
}
This is arguably clearer anyway, because it has better separation of
concerns and uses fewer lines of code to get its job done.
-- Dave Harris, Nottingham, UK.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Mon Jun 13, 2005 10:54 am Post subject: Re: uninitialized variables |
|
|
[email]monade (AT) gmail (DOT) com[/email] wrote:
| Quote: | Isn't this "single-return-guideline" obsolet?
|
Not really. A lot depends on the context.
| Quote: | In the face of exceptions you have to deal with premature
function-exits anyway.
|
Which is, of course, a major drawback of exceptions:-).
In the end, like most other things, it's a cost/benefits trade
off. It's easier to reason about the correctness of code using
single entry/single exit; exceptions are often banned in
critical applications because of the problems they create with
regards to analysing program flow. On the other hand, it is a
lot easier to analyse the code if you ignore error conditions;
generally speaking, if an exception is raised, you don't expect
or require the function to have done everything it normally
does. So you end up with a two stage analysis: you verify
that you have coherent state (so that destructors can be called,
etc.) everywhere an exception must be raised, but you only
verify the complete, correct functionning of the function for
the non-error cases. (I personally think that such analysis can
be accurate enough for critical applications. But the people in
charge of such applications tend to be, understandably,
ultra-conservative.)
Of course, similar analysis can be considered for certain cases
of pre-mature returns. And more generally, while single
entry/single exit may be somewhat simpler to analyse, if the
function is simple enough, it doesn't necessarily matter. There
are a lot of variables, and this is only one.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|