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

How Methods Return Objects

P: n/a
I'd like to know what goes on under the hood when methods return
objects. Eg, I have a simple Point class with two members _x and _y.
It's constructor, copy constructor, assignment operator and additon
operator (which returns another Point object, and which my question is
about) are as follows:

Point::Point(int x, int y) :
_x(x),
_y(y) { }

Point::Point(const Point& p) {
_x = p._x;
_y = p._y;
}

Point& Point::operator=(const Point& p) {
_x = p._x;
_y = p._y;
return (*this);
}

Point Point::operator+(const Point& p) const {
Point ret(_x + p._x, _y + p._y);
return ret;
}

What happens when operator+ returns the temporary Point object that it
creates?

Does it use the copy constructor to create a copy of the temporary
variable "ret"? Is ret destroyed after that?

If not, how does it return a Point object?

Also, why is that "new" never comes into play? How can the compiler
know beforehand how many Point objects will be created via operator+?
Is it because such objects must exist in statements like:

Point p3 = p1 + p2;

I know this is a simple point, but I'm confused nonetheless.

Thanks for any clarification,
cpp

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


P: n/a
"cppaddict" <he***@hello.com> wrote...
I'd like to know what goes on under the hood when methods return
objects. Eg, I have a simple Point class with two members _x and _y.
It's constructor, copy constructor, assignment operator and additon
operator (which returns another Point object, and which my question is
about) are as follows:

Point::Point(int x, int y) :
_x(x),
_y(y) { }

Point::Point(const Point& p) {
_x = p._x;
_y = p._y;
I wonder why you didn't use initialisation here...
}

Point& Point::operator=(const Point& p) {
_x = p._x;
_y = p._y;
return (*this);
}

Point Point::operator+(const Point& p) const {
Point ret(_x + p._x, _y + p._y);
return ret;
}

What happens when operator+ returns the temporary Point object that it
creates?

Does it use the copy constructor to create a copy of the temporary
variable "ret"? Is ret destroyed after that?
Generally speaking, yes. Since 'ret' is an automatic variable, it will
be destroyed right after the function ends (right after the 'return'
statement). In order for the Point object to exist after the function
has finished but before its value is used elsewhere, a temporary one
is created using the copy constructor.

If not, how does it return a Point object?

Also, why is that "new" never comes into play?
How do you know it doesn't? Creation of a temporary _might_ be internally
done using some kind of special form of 'new'. It's not defined, AFAIK.
Where the temporary is created and how is, well, unimportant. At least
from the langauge standpoint.
How can the compiler
know beforehand how many Point objects will be created via operator+?
Every time it has to call operator+ function, another Point object is
potentially created.
Is it because such objects must exist in statements like:

Point p3 = p1 + p2;


The compiler is allowed to forgo creation of a temporary in this case
and instead generate code so that when you return the 'ret' from the
function operator+, it is used to directly initialise the 'p3' object.

You might find all that in good books. Or by looking at the code (yes,
it's usually assembly language) that the compiler generates from your
C++ source.

Victor
Jul 22 '05 #2

P: n/a
Point::Point(const Point& p) {
_x = p._x;
_y = p._y;


I wonder why you didn't use initialisation here...


I should have. Thanks for pointing that out.

Thanks for you other explanations as well.

cpp
Jul 22 '05 #3

P: n/a

cppaddict wrote:
Point::Point(const Point& p) {
_x = p._x;
_y = p._y;


it is unwise to use a leading underscore in a variable name, although in
this case, not technically illegal (17.4.3.1.2).

mark

Jul 22 '05 #4

P: n/a
>it is unwise to use a leading underscore in a variable name, although in
this case, not technically illegal (17.4.3.1.2).

mark


I was under the (mistaken) impression that this was a standard way to
indicate member variables. Do you know what leading underscores are
reserved for? Also, what is the standard way to indicate a member
variable -- trailing underscore?

Thanks,
cpp

Jul 22 '05 #5

P: n/a
"cppaddict" <he***@hello.com> wrote...
it is unwise to use a leading underscore in a variable name, although in
this case, not technically illegal (17.4.3.1.2).

mark


I was under the (mistaken) impression that this was a standard way to
indicate member variables. Do you know what leading underscores are
reserved for? Also, what is the standard way to indicate a member
variable -- trailing underscore?


There is no "standard way" to indicate anything. The Standard prohibits
the use of reserved [by the implementation] names. Such names include
names with double underscores and names that begin with an underscore and
a capital letter.

I am, of course, picking at your use of the word "standard" here. Not
that I have ill will, but traditionally "standard" here means required
or defined by the Standard Document. You might want to use the word
"conventional", as in "what is the conventional way to indicate..."

As to the accepted conventions, there are several. The one I see used
the most is the prefix 'm_' for non-static data members and 's_' for
static data members. Leading underscores, just like trailing underscores,
are not easy to read, that's why most people try to avoid them, I guess.

Victor
Jul 22 '05 #6

P: n/a
On Fri, 30 Jul 2004 03:18:57 GMT, cppaddict <he***@hello.com> wrote:
it is unwise to use a leading underscore in a variable name, although in
this case, not technically illegal (17.4.3.1.2).

mark


I was under the (mistaken) impression that this was a standard way to
indicate member variables. Do you know what leading underscores are
reserved for? Also, what is the standard way to indicate a member
variable -- trailing underscore?

Thanks,
cpp


Its a good way to indicate member variables. I don't understand why some
people claim its dangerous (I am aware of when underscore use is illegal).
Perhaps Mark could justify his claim?

john
Jul 22 '05 #7

P: n/a
John Harrison wrote:

On Fri, 30 Jul 2004 03:18:57 GMT, cppaddict <he***@hello.com> wrote:
it is unwise to use a leading underscore in a variable name, although in
this case, not technically illegal (17.4.3.1.2).

mark


I was under the (mistaken) impression that this was a standard way to
indicate member variables. Do you know what leading underscores are
reserved for? Also, what is the standard way to indicate a member
variable -- trailing underscore?

Thanks,
cpp


Its a good way to indicate member variables. I don't understand why some
people claim its dangerous (I am aware of when underscore use is illegal).
Perhaps Mark could justify his claim?

john


Some say that it's hard to remember the exact rules (never use a leading
underscore followed by an uppercase letter; never use a double underscore;
in the global scope, don't use a leading underscore regardless of the
symbol that follows). There is some potential for an error here,
especially due to code maintenance by those who don't read too much
into language details.
This potential is arguably smaller when using a trailing underscore
instead.

I don't mind it either way (and much prefer them over any alternative),
but in my limited scope the trailing underscore has become more
conventional. I've got used to it and love it.

Denis
Jul 22 '05 #8

P: n/a

"Denis Remezov" <fi***************@yahoo.removethis.ca> wrote in message
news:41***************@yahoo.removethis.ca...
John Harrison wrote:

On Fri, 30 Jul 2004 03:18:57 GMT, cppaddict <he***@hello.com> wrote:
> it is unwise to use a leading underscore in a variable name, although in> this case, not technically illegal (17.4.3.1.2).
>
> mark

I was under the (mistaken) impression that this was a standard way to
indicate member variables. Do you know what leading underscores are
reserved for? Also, what is the standard way to indicate a member
variable -- trailing underscore?

Thanks,
cpp


Its a good way to indicate member variables. I don't understand why some
people claim its dangerous (I am aware of when underscore use is illegal). Perhaps Mark could justify his claim?

john


Some say that it's hard to remember the exact rules (never use a leading
underscore followed by an uppercase letter; never use a double underscore;
in the global scope, don't use a leading underscore regardless of the
symbol that follows). There is some potential for an error here,
especially due to code maintenance by those who don't read too much
into language details.
This potential is arguably smaller when using a trailing underscore
instead.

I don't mind it either way (and much prefer them over any alternative),
but in my limited scope the trailing underscore has become more
conventional. I've got used to it and love it.

Denis


I guess I prefer a leading underscore because its the first thing you see
when you read a name. I guess the same reason you often see m_something but
never something_m.

But yes, beauty is in the eye of the beholder.

john
Jul 22 '05 #9

P: n/a

"John Harrison" <jo*************@hotmail.com> wrote in message
news:opsbxo1yjt212331@andronicus...
On Fri, 30 Jul 2004 03:18:57 GMT, cppaddict <he***@hello.com> wrote:
Its a good way to indicate member variables. I don't understand why some
people claim its dangerous (I am aware of when underscore use is illegal).
Perhaps Mark could justify his claim?


Because they are used by the compiler implementations too.
To quote Herb Sutter here - "Try to avoid names with leading underscores.
Yes, I've habitually used them, and yes, popular books like "Design
Patterns" (Gamma et al) do use it... but the standard reserves some
leading-underscore identifiers for the implementation and the rules are hard
enough to remember (for you and for compiler writers!) that you might as
well avoid this in new code. (Since I'm no longer allowed to use leading
underscores as my "member variable" tag, I'll now use trailing
underscores!)"

This simple program on MS VC 7.0 cribs for ambiguous symbol -

#include <map>
using namespace std;
class _Tree{
};

int main()
{
_Tree t;
}

-Sharad

Jul 22 '05 #10

P: n/a

"Sharad Kala" <no******************@yahoo.com> wrote in message
news:2m************@uni-berlin.de...

"John Harrison" <jo*************@hotmail.com> wrote in message
news:opsbxo1yjt212331@andronicus...
On Fri, 30 Jul 2004 03:18:57 GMT, cppaddict <he***@hello.com> wrote:
Its a good way to indicate member variables. I don't understand why some
people claim its dangerous (I am aware of when underscore use is illegal). Perhaps Mark could justify his claim?


Because they are used by the compiler implementations too.
To quote Herb Sutter here - "Try to avoid names with leading underscores.
Yes, I've habitually used them, and yes, popular books like "Design
Patterns" (Gamma et al) do use it... but the standard reserves some
leading-underscore identifiers for the implementation and the rules are

hard enough to remember (for you and for compiler writers!) that you might as
well avoid this in new code. (Since I'm no longer allowed to use leading
underscores as my "member variable" tag, I'll now use trailing
underscores!)"
I don't find the rule, 'use a leading underscore followed by a lower case
letter for member variables' hard to remember. I would always use a leading
lower case letter in any case even if I wasn't using a leading underscore. I
don't think the argument that you 'might as well' avoid it in new code very
convincing. Why exactly? No bad things are going to happen that I can see.

This simple program on MS VC 7.0 cribs for ambiguous symbol -

#include <map>
using namespace std;
class _Tree{
};

int main()
{
_Tree t;
}

-Sharad


That differs from what I would do in two different ways. First it is
underscore followed by an uppercase letter and second I am only talking
about member variable names.

john
Jul 22 '05 #11

P: n/a
cppaddict posted:
I'd like to know what goes on under the hood when methods return
objects. Eg, I have a simple Point class with two members _x and _y.
It's constructor, copy constructor, assignment operator and additon
operator (which returns another Point object, and which my question is
about) are as follows:

Point::Point(int x, int y) :
_x(x),
_y(y) { }

Point::Point(const Point& p) {
_x = p._x;
_y = p._y;
}

Point& Point::operator=(const Point& p) {
_x = p._x;
_y = p._y;
return (*this);
}

Point Point::operator+(const Point& p) const {
Point ret(_x + p._x, _y + p._y);
return ret;
}

What happens when operator+ returns the temporary Point object that it
creates?

Does it use the copy constructor to create a copy of the temporary
variable "ret"? Is ret destroyed after that?

If not, how does it return a Point object?

Also, why is that "new" never comes into play? How can the compiler
know beforehand how many Point objects will be created via operator+?
Is it because such objects must exist in statements like:

Point p3 = p1 + p2;

I know this is a simple point, but I'm confused nonetheless.

Thanks for any clarification,
cpp

int Blah()
{
return 72;
}

int main()
{
int f = 45 + Blah();
}
When the end of Blah is reached, a temporary is created and this temporary
is given back to main. The temporary lives in main up until the next
semicolon, at which point it's destroyed.

Now, here's one that may result in an optimization:

int Blah()
{
int f = 76;

f *= 2;

f -= 4;

return f;
}

The compiler may choose to return a temporary, which has been copy-
initialized from "f", or it may return "f" itself. If it returns "f" itself,
then there's one less object created, and that's the optimization.

And another optimization:

int Blah()
{
int f = 76;

f *= 2;

f -= 4;

return f;
}

int main()
{
int x = Blah();
}

That x variable in main may be used in Blah, as no temporary is necessary.
And then there's functions that return references...

int k; //global

int& Blah()
{
k = 6783;

k *= 2;

k -= 64;

return k;
}

Here Blah is returning a reference to a global variable, so the global
variable will still exist after the end of Blah, and so it can be used in
main().

If, on the other hand, you do this:

int& Blah()
{
int k = 72;

return k;
}

The Blah function will in fact return a reference to k, but by the time you
get to use it in main, k no longer exists. Compilers warn whenever you
return a reference to a local variable.
And then there's binding to a const-reference:

int Blah()
{
int k = 72;

k +=4;

k *= 2;

return k;
}

int main()
{
const int& monkey = Blah();

//Here, the temporary returned from Blah (or its local variable)
//is directly bound to monkey
//The temporary does NOT get destroyed at the
//next semicolon, but at the end of the reference's
//scope, ie. the end of main
}
You may ask why one would bother binding to a const reference when they can
just do:

int main()
{
int monkey = Blah();
}

and rely on the optimization.

Well, there needn't be an optimization depending on the compiler, and so
monkey may be copy-constructed from the temporary returned by Blah(). Plus,
if Blah returns a const object, then "int monkey" won't optimize, because a
copy will have to be made to yield a non-const version. On the other hand
you could do "const int monkey".

Well anyway, take this code:

int Blah()
{
int k = 42;

k *= 2;

k += 4;

return k;
}

int main()
{
int monkey = Blah();
}
How many "int"s are made? Either 1, 2 or 3. The best compilers will only use
one int, the monkey from main. The monkey will be used in Blah, and then
when Blah finishes, a temporary *won't* be made, it'll just return its local
variable, which is monkey from main!

Another compiler may make 2 "int"s: the monkey in main, and the k in Blah.
The Blah function will return k directly.

And then ofcourse there's compilers that'll make 3 "int"s:

The monkey from main
k from Blah
The temporary returned from Blah

There's times when a function has no choice but to create a temporary to
return, eg.

int Blah()
{
int k = 7;

return k + 4;
}

But if you return the variable directly, and there's no constness problems,
then there's no problems with the actual local variable being returned.

All of these are just optimizations, and needn't be performed.

(Another even better compiler may turn the above function into:

int Blah()
{
int k = 7;

return k += 4;
}

And return "k" itself, as it can see that there's no consequences of adding
the 4 to k directly. One less temporary.
-JKop

Jul 22 '05 #12

P: n/a
JKop,

Thanks for that discussion... very interesting.

cpp
Jul 22 '05 #13

P: n/a
cppaddict wrote:

Point Point::operator+(const Point& p) const {
Point ret(_x + p._x, _y + p._y);
return ret;
}


I would prefer having binary operators as non-member functions, like
this:

Point operator+(const Point& p1, const Point& p2) {
Point ret(p1._x + p2._x, p1._y + p2._y);
return ret;
}
What do you think?

Niels Dekker
www.xs4all.nl/~nd/dekkerware
Jul 22 '05 #14

P: n/a
In message <41***************@this.is.invalid>, "Niels Dekker (no reply
address)" <un*****@this.is.invalid> writes
cppaddict wrote:

Point Point::operator+(const Point& p) const {
Point ret(_x + p._x, _y + p._y);
return ret;
}


I would prefer having binary operators as non-member functions, like
this:

Point operator+(const Point& p1, const Point& p2) {
Point ret(p1._x + p2._x, p1._y + p2._y);
return ret;
}
What do you think?


I think I'd implement non-member operator+() in terms of member
operator+=().
--
Richard Herring
Jul 22 '05 #15

P: n/a
cppaddict wrote:

Point Point::operator+(const Point& p) const {
Point ret(_x + p._x, _y + p._y);
return ret;
}
I wrote:
I would prefer having binary operators as non-member functions [...]

Richard Herring wrote:
I think I'd implement non-member operator+() in terms of member
operator+=().

So I guess you mean like this:

Point& Point::operator+=(const Point& p) {
_x += p._x;
_y += p._y;
return *this;
}

Point operator+(const Point& p1, const Point& p2) {
return Point(p1) += p2;
}
Would you write other binary operators, like operator!=, as non-members
as well? In what situation would you prefer to implement a binary
operator as a member function?

Thanks in advance,

Niels Dekker
www.xs4all.nl/~nd/dekkerware
Jul 22 '05 #16

P: n/a
In message <41***************@this.is.invalid>, "Niels Dekker (no reply
address)" <un*****@this.is.invalid> writes
cppaddict wrote:

Point Point::operator+(const Point& p) const {
Point ret(_x + p._x, _y + p._y);
return ret;
}
I wrote:

I would prefer having binary operators as non-member functions [...]

Richard Herring wrote:

I think I'd implement non-member operator+() in terms of member
operator+=().

So I guess you mean like this:

Point& Point::operator+=(const Point& p) {
_x += p._x;
_y += p._y;
return *this;
}

Point operator+(const Point& p1, const Point& p2) {
return Point(p1) += p2;
}

Exactly.

Would you write other binary operators, like operator!=, as non-members
as well?
Yes, if both their operands are const and of the same type. That way,
you get the same rules for automatic type conversions applied to both
operands. With member functions, the first operand is treated
differently, with the possibility that a op b and b op a produce
different conversions if a and b are of different (but convertible)
types.
In what situation would you prefer to implement a binary
operator as a member function?

If the function modifies its argument (e.g. operator+= above.).

--
Richard Herring
Jul 22 '05 #17

P: n/a
Richard Herring wrote:
In message <41***************@this.is.invalid>, "Niels Dekker (no reply
[...]
In what situation would you prefer to implement a binary
operator as a member function?

If the function modifies its argument (e.g. operator+= above.).


Operator += is an assignment operator and it cannot be implemented as
a non-member, no matter whether it in fact modifies its left operand
or not (and it is up to you to decide whether it does modify it).

There are operators that can be made non-members and there are others
that cannot. For example, type conversion operators must be members
because such is the requirement of the language. They most likely do
not modify their operand, however.

V
Jul 22 '05 #18

P: n/a
Victor Bazarov wrote in news:VZsOc.248$191.84
@newsread1.dllstx09.us.to.verio.net in comp.lang.c++:
Richard Herring wrote:
In message <41***************@this.is.invalid>, "Niels Dekker (no reply
[...]
In what situation would you prefer to implement a binary
operator as a member function?
If the function modifies its argument (e.g. operator+= above.).


Operator += is an assignment operator and it cannot be implemented as
a non-member, no matter whether it in fact modifies its left operand
or not (and it is up to you to decide whether it does modify it).


#include <iostream>
#include <ostream>

struct X {};

X &operator += ( X &lhs, X const & )
{
std::cout << "Ok" << std::endl;
return lhs;
}

int main()
{
X a, b;
a += b;
}

Works fine for me.
There are operators that can be made non-members and there are others
that cannot. For example, type conversion operators must be members
because such is the requirement of the language. They most likely do
not modify their operand, however.


Also operator ->(), I can't remember any others (*).

*) Ok, new and delete, but I don't think they count :).

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #19

P: n/a
Rob Williscroft wrote:
Victor Bazarov wrote in news:VZsOc.248$191.84
@newsread1.dllstx09.us.to.verio.net in comp.lang.c++:

Richard Herring wrote:
In message <41***************@this.is.invalid>, "Niels Dekker (no reply
[...]

In what situation would you prefer to implement a binary
operator as a member function?
If the function modifies its argument (e.g. operator+= above.).
Operator += is an assignment operator and it cannot be implemented as
a non-member, no matter whether it in fact modifies its left operand
or not (and it is up to you to decide whether it does modify it).

#include <iostream>
#include <ostream>

struct X {};

X &operator += ( X &lhs, X const & )
{
std::cout << "Ok" << std::endl;
return lhs;
}

int main()
{
X a, b;
a += b;
}

Works fine for me.


Perhaps it's my misreading of the Standard. First it calls all @=
operators "assignment operators" (@ denotes an operation like + or -)
then it says that the assignment operator has to be a member, but when
it gives an example it only speaks of operator=. Does that mean that
operators like += don't have to be members? Perhaps that's open to
interpretation. Perhaps not. I will ask for clarification in the
standard newsgroup.

There are operators that can be made non-members and there are others
that cannot. For example, type conversion operators must be members
because such is the requirement of the language. They most likely do
not modify their operand, however.

Also operator ->(), I can't remember any others (*).

*) Ok, new and delete, but I don't think they count :).


They are actually static, while not declared so. Very unusual.

V
Jul 22 '05 #20

P: n/a
Victor Bazarov wrote in news:HrtOc.250$191.200
@newsread1.dllstx09.us.to.verio.net in comp.lang.c++:
Works fine for me.
Perhaps it's my misreading of the Standard. First it calls all @=
operators "assignment operators" (@ denotes an operation like + or -)
then it says that the assignment operator has to be a member, but when
it gives an example it only speaks of operator=. Does that mean that
operators like += don't have to be members? Perhaps that's open to
interpretation. Perhaps not.


Yep, I just looked and I see your point.
I will ask for clarification in the
standard newsgroup.


Sounds good, though AFAICT Exsisting Practice(tm) is that operator @=
can be a non-member, so the question is really "does the standard need
clarification".

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #21

P: n/a
cppaddict wrote:

JKop,

Thanks for that discussion... very interesting.

cpp


Replace int with a user-defined type and what JKop wrote will
probably make sense (I haven't checked it closely).

In respect to type int, his story may still be "as-if"-correct
but is actually misleading in a practical sense. Very crudely
put, type int is small, cheap to copy, and is typically subject
to machine treatment not generally available to larger-sized
user-defined types.

For example, more often than not,
int const& f(int const& x) {...}

will be the same speed (if the compiler optimises it) as or a tiny
bit slower (because of indirection) than
int f(int x) {...}

Not that you should worry too much about that, but you can see
for yourself how things work by using your debugger to step
through the assembly code (optimised and unoptimised).

Denis
Jul 22 '05 #22

P: n/a

John Harrison wrote:
On Fri, 30 Jul 2004 03:18:57 GMT, cppaddict <he***@hello.com> wrote:
it is unwise to use a leading underscore in a variable name, although in
this case, not technically illegal (17.4.3.1.2).

[snip] (but note that the numbers in parentheses refer to a paragraph in
the standard related to this).
I was under the (mistaken) impression that this was a standard way to
indicate member variables. Do you know what leading underscores are
reserved for? Also, what is the standard way to indicate a member
variable -- trailing underscore?

[snip]
Its a good way to indicate member variables. I don't understand why
some people claim its dangerous (I am aware of when underscore use is
illegal). Perhaps Mark could justify his claim?


as i pointed out it is not technically illegal to use a leading
underscore in this case. most people know that double underscores are
reserved, and many know that an underscore followed by an uppercase
letter is reserved also.

however, leading underscores followed by a lowercase letter are reserved
for the implementation for use in the global namespace. most people
don't know that.

in my mind it makes little sense to use leading underscores when there
are so many restrictions and caveats. is it ok to use an underscore
followed by a number? (yes, as long as it's not in the global
namespace). what if you're dealing with programmers who don't speak a
latin-based language natively, and who have to consult a reference in
order to remember what's uppercase and what's lowercase? (afaict, the
standard doesn't even bother to define that, which tells me that it
doesn't care about splitting the difference most of the time, so why here?)

to hell with it all. i just say no leading underscores at all. use
trailing underscores, if anything; there are no restrictions on those.
or prefix "m_". whatever you want, as long as it's clear. i think
leading underscores, with all their hazards, are not particularly clear.
but i live in a free country, so i won't tell anyone else what to do.

mark

Jul 22 '05 #23

P: n/a
"John Harrison" <jo*************@hotmail.com> wrote in message
news:2m************@uni-berlin.de...
I don't find the rule, 'use a leading underscore followed by a lower case
letter for member variables' hard to remember. I would always use a leading lower case letter in any case even if I wasn't using a leading underscore. I don't think the argument that you 'might as well' avoid it in new code very convincing. Why exactly? No bad things are going to happen that I can see.


Most of this is a matter of personal taste, so while no bad things will
happen, some folks may not like it. Personally, I don't like leading
underscores because that naming convention is used by the implementation in
the global namespace, which can make the code look like it is referencing
implementation-specific symbols when it is not. Every time I see a leading
underscore, I think "implementation-specific functionality." Granted, I can
think for a second and realize that the code is referencing a member, but
the main reason for using a different convention for members is that it
makes them look different from other symbols and therefore makes the code
easier to read. Using a naming convention that is already used elsewhere
can almost defeat the purpose of using the convention in the first place.

--
David Hilsee
Jul 22 '05 #24

P: n/a
On Sat, 31 Jul 2004 19:38:18 -0400, David Hilsee
<da*************@yahoo.com> wrote:
"John Harrison" <jo*************@hotmail.com> wrote in message
news:2m************@uni-berlin.de...
I don't find the rule, 'use a leading underscore followed by a lower
case
letter for member variables' hard to remember. I would always use a

leading
lower case letter in any case even if I wasn't using a leading
underscore.

I
don't think the argument that you 'might as well' avoid it in new code

very
convincing. Why exactly? No bad things are going to happen that I can
see.


Most of this is a matter of personal taste, so while no bad things will
happen, some folks may not like it. Personally, I don't like leading
underscores because that naming convention is used by the implementation
in
the global namespace, which can make the code look like it is referencing
implementation-specific symbols when it is not. Every time I see a
leading
underscore, I think "implementation-specific functionality." Granted, I
can
think for a second and realize that the code is referencing a member, but
the main reason for using a different convention for members is that it
makes them look different from other symbols and therefore makes the code
easier to read. Using a naming convention that is already used elsewhere
can almost defeat the purpose of using the convention in the first place.


That's a fair point, although in my coding I very rarely use such
implementation-specific symbols.

Maybe I should give the trailing underscore method a go, see if I too can
learn to love it.

john
Jul 22 '05 #25

P: n/a
In message <VZ**************@newsread1.dllstx09.us.to.verio.n et>, Victor
Bazarov <v.********@comAcast.net> writes
Richard Herring wrote:
In message <41***************@this.is.invalid>, "Niels Dekker (no
reply [...]
In what situation would you prefer to implement a binary
operator as a member function?

If the function modifies its argument (e.g. operator+= above.).


Operator += is an assignment operator and it cannot be implemented as
a non-member, no matter whether it in fact modifies its left operand
or not (and it is up to you to decide whether it does modify it).


True, but if it doesn't do so, and do it in a way consistent with
operator+ and operator= (and probably also operators - and -= and maybe
++ and --) I humbly suggest you should be calling them something else,
on the principle of least surprise.

--
Richard Herring
Jul 22 '05 #26

This discussion thread is closed

Replies have been disabled for this discussion.