Style: preferring parentheses to '=' for initialization?

L

Luke Meyers

Lately I find myself increasingly preferring the practice of going
ever-so-slightly out of my way to avoid the use of the form of
initialization which uses the '=' symbol, on the grounds that it can be
mistaken too easily for assignment. I like the avoidance of mistakes.
I like even more the frequent, subtle reinforcement (for myself and my
colleagues) of the point that assignment and initialization are
entirely different operations.

However, there are counterpoints. First, I still fall into old habits
-- I don't consider this a major problem, since the worst that can
happen is that I am a little inconsistent (which is the case anyway,
and probably to greater degree, unless one is religious in the other
direction and always uses '='). Of more significant concern is
readability. Due to old habits, in some cases I find the code slightly
less readable under this practice, though I expect this to diminish
with time. I have to be concerned with my colleagues as well, though.

So, what do you all think? Does anyone else do this? How do you feel
about the readability issue? Any other considerations I've failed to
identify?

Luke
 
A

Alan Johnson

Luke said:
Lately I find myself increasingly preferring the practice of going
ever-so-slightly out of my way to avoid the use of the form of
initialization which uses the '=' symbol, on the grounds that it can be
mistaken too easily for assignment. I like the avoidance of mistakes.
I like even more the frequent, subtle reinforcement (for myself and my
colleagues) of the point that assignment and initialization are
entirely different operations.

However, there are counterpoints. First, I still fall into old habits
-- I don't consider this a major problem, since the worst that can
happen is that I am a little inconsistent (which is the case anyway,
and probably to greater degree, unless one is religious in the other
direction and always uses '='). Of more significant concern is
readability. Due to old habits, in some cases I find the code slightly
less readable under this practice, though I expect this to diminish
with time. I have to be concerned with my colleagues as well, though.

So, what do you all think? Does anyone else do this? How do you feel
about the readability issue? Any other considerations I've failed to
identify?

Luke

One issue you need it be aware of (if you aren't already) is the weird
parsing issue you can run into when trying to construct an object with
an unnamed temporary. Consider the following example:

class A
{
public:
explicit A(int) {}
} ;

class B
{
public:
explicit B(const A &) {}
int f() { return 42 ; }
} ;


int main()
{
int x = 3 ;
B b(A(x)) ;

b.f() ; // Oops! b isn't a variable like you expected!
}


The line of interest is:
B b(A(x)) ;

You'd think this would create an unnamed temporary of type A, and pass
it to B's constructor. However, it turns out that when declaring a
function, you are allowed to put parenthesis around the argument names.
So C++ will actually interpret this line as:
B b(A x) ;

That is, the declaration of a function named b that returns an object of
type B and takes one parameter of type A. The particularly troublesome
part is that there is no syntax problem there, so you don't get an error
until you actually try to use b. This problem is avoided with the '='
syntax for initialization. Example:
B b = B(A(x)) ;

Another solution, if you still prefer to leave '=' out of your
initialization, is to introduce another set of parenthesis:
B b((A(x))) ;
 
R

Roy Smith

Alan Johnson said:
Another solution, if you still prefer to leave '=' out of your
initialization, is to introduce another set of parenthesis:
B b((A(x))) ;

Ugh. Why not just make it explicit with a temporary intermediate:

A temp(x);
B b(temp);

Sure, it takes two lines instead of one, but it's easy to read and
completely unambiguous. Let the compiler worry about optimizing away the
temporary.
 
V

Victor Bazarov

Roy said:
Ugh. Why not just make it explicit with a temporary intermediate:

A temp(x);
B b(temp);

Sure, it takes two lines instead of one, but it's easy to read and
completely unambiguous. Let the compiler worry about optimizing away
the temporary.

It's not a temporary, at least AFA the compiler is concerned. It is
a full-fledged object (with a very common name, mind you), introduced
into the same scope as the intented ('b') object. So, there is no
sense in trying to mask that by calling it "temporary". The term has
a very specific and well-defined meaning in C++.

V
 
B

Boris Kolpackov

Alan Johnson said:
One issue you need it be aware of (if you aren't already) is the weird
parsing issue you can run into when trying to construct an object with
an unnamed temporary.

Another one is a declaration in an if-statement:

if (int i (f ())) // syntax error
if (int i = f ()) // ok

I, however, still prefer the construction syntax despite some annoying
inconsistencies in the language.

-boris
 
T

Tomás

Luke Meyers posted:
Lately I find myself increasingly preferring the practice of going
ever-so-slightly out of my way to avoid the use of the form of
initialization which uses the '=' symbol, on the grounds that it can be
mistaken too easily for assignment. I like the avoidance of mistakes.
I like even more the frequent, subtle reinforcement (for myself and my
colleagues) of the point that assignment and initialization are
entirely different operations.


Okey dokey... well here's how I do it:


If I'm dealing with a primitive type, then I just do the following:

unsigned k = 7;

It's natural, and it's "the way things were supposed to be".


If I'm dealing with a Fancy Class Type, then I use the parentheses method.
It makes more sense because you're calling a constructor like a function:

Integer k(7);


If I want to default-initialise an array or an aggregate, then I:


double array[50] = {};

SomePOD obj = {};

SomePod array2[5] = {};


If I want maximum flexibility when writing a template, I use a little
thingie called "DefaultInitBearer" which provides me with a universal way
of default initialising any kind of object.

There's something which you haven't taken into account. The following two
statements *aren't* equivalent:

Integer k = 7;
Integer k(7);


And I'll demonstrate by using the following code:


class Integer {
private:

Integer(const Integer &);
/* Can't copy-construct */

public:

Integer(int const x) {}
};


int main()
{
Integer a(7); /* Compiles without effort */

Integer b = 7; /* Won't compile */
}

There reason why the second one won't compile is because:

Integer b = 7;

is interpretted as:

Integer b = Integer(7);

which is interpretted as:

Integer b( Integer(7) );

Can you see the copy construction? You would be correct in thinking that
any compiler worth its salt would optimize away the copy-construction, BUT
the class in question STILL must have the ability to be copy constructed.
So... here's what I advocate:

Treat POD's and Fancy Class Types different... because they ARE different,
and initialise them respectively as follows:

int k = 5;

Integer k(5);


-Tomás
 
V

Victor Bazarov

Tomás said:
[..]
If I'm dealing with a Fancy Class Type, then I use the parentheses
method. It makes more sense because you're calling a constructor

Please don't confuse newbies with improper terminology. You're not
"calling a constructor". You're constructing (and initialising)
an object.

V
 
T

Tomás

Victor Bazarov posted:
Tomás said:
[..]
If I'm dealing with a Fancy Class Type, then I use the parentheses
method. It makes more sense because you're calling a constructor

Please don't confuse newbies with improper terminology. You're not
"calling a constructor". You're constructing (and initialising)
an object.


I didn't think he was a newbie (he refers to his "colleagues" multiple
times). I figured he was an experienced C++ programmer who put his doctrine
book down for a few minutes to think for himself.

-Tomás
 
V

Victor Bazarov

Tomás said:
Victor Bazarov posted:
Tomás said:
[..]
If I'm dealing with a Fancy Class Type, then I use the parentheses
method. It makes more sense because you're calling a constructor

Please don't confuse newbies with improper terminology. You're not
"calling a constructor". You're constructing (and initialising)
an object.


I didn't think he was a newbie (he refers to his "colleagues" multiple
times). I figured he was an experienced C++ programmer who put his
doctrine book down for a few minutes to think for himself.

I wasn't talking about the OP. Newbies read this newsgroup too, if you
didn't know. They will see your post and decide that it's possible to
"call a constructor". If you wanted to communicate to the OP exclusively,
use private e-mail.

V
 
T

Tomás

Victor Bazarov posted:
They will see your post and decide that it's
possible to "call a constructor".


I've never liked the word "newbie" -- it's patronising. When I was a
novice C++ programmer, I would have preferred to be referred to as a
"novice" or "beginner".


If any novice would like to call a constructor:


#include <string>
#include <iostream>

int main()
{

/* Allocate the memory */

unsigned char (&buffer)[ sizeof(std::string) ]
= *new unsigned char[1][ sizeof(buffer) ];


/* Call the constructor */

std::string &str = *new(buffer) std::string("Hello World!");


/* Use the object */

std::cout << str;


/* Call the destructor */


typedef std::string stringForDestructorCall;

str.~stringForDestructorCall();


/* Deallocate the memory */


delete [] &buffer;
}}
 
V

Victor Bazarov

Tomás said:
Victor Bazarov posted:



I've never liked the word "newbie" -- it's patronising. When I was a
novice C++ programmer, I would have preferred to be referred to as a
"novice" or "beginner".

So? What's your point? That I am patronising? Towards whom? Novices?
Beginners? Get back on topic.
If any novice would like to call a constructor:

[...more confusion...]

There is no need to crawl into a bottle here. What you posted is not
a call to a constructor. Period. The use of placement new does in fact
resolve into a constructor being invoked, but so does a call to a regular
'new' or an introduction of a temporary or simple object definition. Did
you intend to somehow isolate the placement new and give it some special
meaning WRT "calling a constructor"? Well, what you've accomplished is
spreading more confusion. Please refrain from that.

If you need a good explanation about why it's not possible to call
a constructor, please refer to news archives, that topic has been covered
extensively.

V
 
T

Tomás

Victor Bazarov posted:

Did you intend to somehow isolate the placement new and give it some
special meaning WRT "calling a constructor"?

Yes, exactly.

Your argument is about semantics, nothing more.

If I say that a door is "opened", rather than "open", then you may infer
from the nuance what you like... but there's no clear-cut distinction
between an "open door" and an "opened door" -- so there's room to speculate
on how they're similar, and how they're different.

So what nuance do you suppose there is between "calls a contructor" and
"constructs an object"?

If you don't want to say that "placement new" calls a constructor, then by
all means, go ahead -- you may say that it "contructs an object" or
"initialises an object", if you like.

However, I will continue to state that "placement new calls a
constructor"... Why? Because it makes sense.

We both seem to have a high enough command of English to come up with our
own terminology... so you can "construct an object" while I "call a
constructor".

-Tomás
 
V

Victor Bazarov

Tomás said:
Victor Bazarov posted:


special meaning WRT "calling a constructor"?

Yes, exactly.

Are you not listening? How is 'placement new' different from, say,
a regular 'new', then, in this particular aspect? I am not talking
about allocation of memory. I am specifically talking about object
construction (and invoking a constructor if there is one).
Your argument is about semantics, nothing more.

Nothing more? Do you mean to say that semantics (meaning) is not
important? You seem to be tripping yourself here.
If I say that a door is "opened", rather than "open", then you may
infer from the nuance what you like... but there's no clear-cut
distinction between an "open door" and an "opened door" -- so there's
room to speculate on how they're similar, and how they're different.

Yes, there is. But I am not going to debate it with you [here]. You can
go to 'alt.usage.english' and ask there, and try to convince everybody
*there* that there is no difference.
So what nuance do you suppose there is between "calls a contructor"
and "constructs an object"?

Simple. It is possible to construct an object without "calling"
a constructor, if the object is of POD type, for example. It is not
possible to call a constructor in a program, only to do something so
that it gets invoked. There is a difference between "calling" and
"causing an invocation". If you don't understand it, there is nothing
to discuss. Go learn that difference first, then come back.
If you don't want to say that "placement new" calls a constructor,
then by all means, go ahead -- you may say that it "contructs an
object" or "initialises an object", if you like.

However, I will continue to state that "placement new calls a
constructor"... Why? Because it makes sense.

I think you've managed to confuse yourself here. Yes, placement new
calls a constructor. Somehow. Magically. My point, and I insist on
it, is that the programmer has no means to "call a constructor". The
constructor gets invoked, that's all.

A constructor is a member function without a name. It cannot be looked
up during regular name lookup. Hence it can't be called. See how the
Standard defines a function call and a member function call.
We both seem to have a high enough command of English to come up with
our own terminology... so you can "construct an object" while I "call
a constructor".

You say what you will, in your own home, talking to your SO. Here we
use the terms and concepts set forth by the language Standard. Do you
understand that? That's why I asked you to stop spreading confusion.

V
 
K

Kai-Uwe Bux

Victor said:
Tomás wrote: [snip]
If any novice would like to call a constructor:

[...more confusion...]
[snip]

If you need a good explanation about why it's not possible to call
a constructor, please refer to news archives, that topic has been covered
extensively.

Yes, and it appears to be a religious war in which you happen to be on one
side. The issue is far less clear cut than you imply. The standard itself
uses the terminology that a constructor "is called" (although it does not
say by whom). Sometimes, but not always, the phrase is qualified as "is
implicitly called".


Best

Kai-Uwe Bux
 
T

Tomás

Victor Bazarov posted:

Are you not listening? How is 'placement new' different from, say,
a regular 'new', then, in this particular aspect? I am not talking
about allocation of memory. I am specifically talking about object
construction (and invoking a constructor if there is one).


There comes a point where you assume that everyone understands you enough
so that you don't have to state the obvious. For example if I give
someone the following code snippet:

int main()
{
string str;

cout << str;
}

If someone replies saying: "There's no such class as string, no such
object as cout", then I'll reply, "Use your brain and presume that I took
a shortcut and left out the necessary include's and using declarations".

I am well aware that "placement new" isn't as cut-and-dried as "oh, it
calls the constructor". Here's an example:

struct Monkey {
string s;
}

int main()
{
void * const p = malloc( sizeof(Monkey) );

new(p) Monkey;
}


But in the context of this conversation, it does bear such simplicity --
if you want to explicitly call a constructor then use "placement new".
Thus, I say that "placement new" calls the constructor.

Nothing more? Do you mean to say that semantics (meaning) is not
important? You seem to be tripping yourself here.


There's no doubt in my mind that we both know what we're talking about
with regard to the C++ Programming Language. We're just arguing over how
we have expressed our understanding -- thus I say it's to do with
"semantics".

If I say that a door is "opened", rather than "open", then you may
infer from the nuance what you like... but there's no clear-cut
distinction between an "open door" and an "opened door" -- so there's
room to speculate on how they're similar, and how they're different.

Yes, there is. But I am not going to debate it with you [here]. You can
go to 'alt.usage.english' and ask there, and try to convince everybody
*there* that there is no difference.


I've been on that newsgroup before... a perfect example of people who
can't see the woods for the trees. The trick to understanding language is
not thinking. (But that's not exactly topical here)

Simple. It is possible to construct an object without "calling"
a constructor, if the object is of POD type, for example.


Yes, but in the context of this conversation, only a brain amputee would
use placement new on a POD. (Leaving out template code of course).

It is not
possible to call a constructor in a program, only to do something so
that it gets invoked.


Again, semantics.

If you have a Fancy Class, and you use placement new on it, then its
constructor gets called. Fair enough if you want to say that this is
simply a consequence of placement new; but in my eyes, the programmer's
intent was to simply call a constructor, and thus, placement can be used
to call a constructor.

There is a difference between "calling" and
"causing an invocation".


I presume you're talking about a "call" always being explicit, and an
"invocation" sometimes being implicit:

class Invocation {};

class Call : public Invocation {};

I think you've managed to confuse yourself here. Yes, placement new
calls a constructor.


Which is the basis of my argument.

Somehow. Magically.


Indeed again you're correct -- but this does not proclude from the
programmer's intention:

Programmer intended to call the constructor, so programmer used placement
new.

My point, and I insist on
it, is that the programmer has no means to "call a constructor". The
constructor gets invoked, that's all.


You're using your own definition of "call" and "invoke". There's nothing
in my mind which probhibits a "call" from being implicit.

A constructor is a member function without a name.


That's entirely just a perspective, a point of view, a way of looking at
things. Many more people would say, "It's a member function whose name is
identical to that of the class."

It cannot be looked
up during regular name lookup. Hence it can't be called. See how the
Standard defines a function call and a member function call.

Does the Standard make a distinction between a "call" and an
"invocation"? If it does, I wasn't aware of it, but I'll be more than
happy to change my use of language from here on in if so.

You say what you will, in your own home, talking to your SO.


SO? Never seen that abbreviation before; could you explain it please?
Anyway, I speak Irish at home.

Here we
use the terms and concepts set forth by the language Standard. Do you
understand that? That's why I asked you to stop spreading confusion.


Oh... I think I finally understand the crux of this argument -- are you
basing your stance on the distinction between a "call" and an
"invocation"?


-Tomás
 
M

mlimber

Kai-Uwe Bux said:
Victor said:
Tomás wrote: [snip]
If any novice would like to call a constructor:

[...more confusion...]
[snip]

If you need a good explanation about why it's not possible to call
a constructor, please refer to news archives, that topic has been covered
extensively.

Yes, and it appears to be a religious war in which you happen to be on one
side. The issue is far less clear cut than you imply. The standard itself
uses the terminology that a constructor "is called" (although it does not
say by whom). Sometimes, but not always, the phrase is qualified as "is
implicitly called".

I don't see this as contradicting Victor's point: a constructor can be
called but not *directly* by the user -- it can only be implicitly
invoked.

Cheers! --M
 
V

Victor Bazarov

Kai-Uwe Bux said:
Victor said:
Tomás wrote: [snip]
If any novice would like to call a constructor:

[...more confusion...]
[snip]

If you need a good explanation about why it's not possible to call
a constructor, please refer to news archives, that topic has been
covered extensively.

Yes, and it appears to be a religious war in which you happen to be
on one side.

Pardon me, but why did you use the term "religious"? What's religious
about it?

It would have to be a really compelling reason to change side in this
issue. Do you have a reason to state?
The issue is far less clear cut than you imply. The
standard itself uses the terminology that a constructor "is called"
(although it does not say by whom). Sometimes, but not always, the
phrase is qualified as "is implicitly called".

I am not going to ask you to take part in that alleged "war", but if
*you* cannot determine whose side to take after reading the Standard
[and probably the news for some time], then how could a newbie deduce
that simple thing that he/she cannot call a constructor but only cause
the constructor to "be called" (passive voice only)?

V
 
T

Tomás

Victor Bazarov posted:
Kai-Uwe Bux said:
Victor said:
Tomás wrote: [snip]
If any novice would like to call a constructor:

[...more confusion...] [snip]

If you need a good explanation about why it's not possible to call
a constructor, please refer to news archives, that topic has been
covered extensively.

Yes, and it appears to be a religious war in which you happen to be
on one side.

Pardon me, but why did you use the term "religious"? What's religious
about it?


Just a figure of speech... if someone is overly pedantic or obsessive
about something then they're said to be "religious" about it. He may also
be suggesting that the argument is centered more on stubbornness to
change one's viewpoint, rather than logic.

It would have to be a really compelling reason to change side in this
issue. Do you have a reason to state?
The issue is far less clear cut than you imply. The
standard itself uses the terminology that a constructor "is called"
(although it does not say by whom). Sometimes, but not always, the
phrase is qualified as "is implicitly called".

I am not going to ask you to take part in that alleged "war", but if
*you* cannot determine whose side to take after reading the Standard
[and probably the news for some time], then how could a newbie deduce
that simple thing that he/she cannot call a constructor but only cause
the constructor to "be called" (passive voice only)?


At the end of the day, a novice can still have the following thought
patterns:

"Hmm... right I've allocated memory; oh but this is a Fancy Class
Type, so I need to call its constructor too... ah I know, I'll use
placement new to call the constructor".

Granted, "placement new" can do more than simply call a class's
constructor (e.g. it can call the constructor of member objects), but
nonetheless, programmers DO use it simply with the intention of calling a
constructor.

If someone said to me: "You can't call a constructor explicitly", then
I'd show them "placement new".

-Tomás
 
H

Howard Hinnant

Boris Kolpackov said:
Another one is a declaration in an if-statement:

if (int i (f ())) // syntax error
if (int i = f ()) // ok

I, however, still prefer the construction syntax despite some annoying
inconsistencies in the language.

Still another issue is with generic code:

template <class T>
void swap(T& x, T& y)
{
T tmp = x;
x = y;
y = tmp;
}

as coded above this requires T to have a *non-explicit* copy
constructor. But:

template <class T>
void swap(T& x, T& y)
{
T tmp(x);
x = y;
y = tmp;
}

will work with a T with an explicit copy constructor. (I'm still trying
to figure out why anyone would *want* an explicit copy constructor).

-Howard
 
M

mlimber

Victor said:
Pardon me, but why did you use the term "religious"? What's religious
about it?

I think he just means a discussion that has raised strong convictions
(like where the curly braces ought to go but even moreso). I would
suggest, however, that Tomás is the one who first linked this
discussion with religious conviction with his derisive use of the word
"doctrine" (here and in other threads), which certainly has a
religious/dogmatic connotation that he intends to invoke.

Cheers! --M
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,681
Members
48,796
Latest member
Greg L.

Latest Threads

Top