Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Returning const objects?

Reply
Thread Tools

Returning const objects?

 
 
Derek
Guest
Posts: n/a
 
      01-06-2005
Some authors advocate returning const objects:

const Point operator+(const Point&, const Point&);
^^^^^

Returning a const object prevents some bad code from compiling:

Point a, b, c;
(a + b) = c; // error

But it also prevents some potentially convenient constructs:

Point a, b, c;
a = (b + c).normalize(); // error

The best argument I've heard to settle this standoff is that
returning const objects makes them behave like built-in types:

int x, y, z, w;
x = (y + z) *= w; // error

Are there any other compelling reasons to adopt/ignore this
convention?
 
Reply With Quote
 
 
 
 
Gianni Mariani
Guest
Posts: n/a
 
      01-06-2005
Derek wrote:
> Some authors advocate returning const objects:
>
> const Point operator+(const Point&, const Point&);
> ^^^^^
>
> Returning a const object prevents some bad code from compiling:
>
> Point a, b, c;
> (a + b) = c; // error
>
> But it also prevents some potentially convenient constructs:
>
> Point a, b, c;
> a = (b + c).normalize(); // error


What's stopping you from creating a "const" version of normalize that
returns a copy of a normalized Point ?

i.e.

class Point
{
..... blah ....

Point & normalize();
const Point normalize() const;
};

>
> The best argument I've heard to settle this standoff is that
> returning const objects makes them behave like built-in types:
>
> int x, y, z, w;
> x = (y + z) *= w; // error
>
> Are there any other compelling reasons to adopt/ignore this
> convention?

 
Reply With Quote
 
 
 
 
Howard
Guest
Posts: n/a
 
      01-06-2005

"Derek" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Some authors advocate returning const objects:
>
> const Point operator+(const Point&, const Point&);
> ^^^^^
>
> Returning a const object prevents some bad code from compiling:
>
> Point a, b, c;
> (a + b) = c; // error
>
> But it also prevents some potentially convenient constructs:
>
> Point a, b, c;
> a = (b + c).normalize(); // error


Or you can do it like I would:

Point a(b+c);
a.normalize();

Less convenient? Maybe, but it's clear, and easy to debug. My rule: do one
thing at a time.

-Howard



 
Reply With Quote
 
Howard Hinnant
Guest
Posts: n/a
 
      01-06-2005
In article <(E-Mail Removed)>, Derek <(E-Mail Removed)>
wrote:

> Some authors advocate returning const objects:
>
> const Point operator+(const Point&, const Point&);
> ^^^^^
>
> Returning a const object prevents some bad code from compiling:
>
> Point a, b, c;
> (a + b) = c; // error
>
> But it also prevents some potentially convenient constructs:
>
> Point a, b, c;
> a = (b + c).normalize(); // error
>
> The best argument I've heard to settle this standoff is that
> returning const objects makes them behave like built-in types:
>
> int x, y, z, w;
> x = (y + z) *= w; // error
>
> Are there any other compelling reasons to adopt/ignore this
> convention?


My vote is to ignore this convention. Good conventions prevent
/accidental/ errors. When was the last time you saw something like this
happen by accident:

(a + b) = c; // error

?!

I've never seen it happen. Otoh, I have personally used constructs like:

a = (b + c).normalize();

and would be frustrated if the return of op+ forced me to make a useless
copy:

a = Point(b + c).normalize();

It would be more fun to just insert sleep cycles in my code. :-\

Looking at the evolution of C++, I believe we will see move semantics in
C++0X (I'm currently working very hard to make that happen). And const
return types will defeat the tremendous performance optimizations made
by move semantics.

Reference:

http://www.open-std.org/jtc1/sc22/wg...004/n1690.html

Consider:

std::vector<int>
foo(unsigned n)
{
return std::vector<int>(n);
}

int main()
{
std::vector<int> v;
v = foo(3);
}

Today this code will go to the heap at least twice:

1. To create the vector inside of foo.
2. To assign from foo's return to v.

On some compilers you may actually go to the heap 3 times (if RVO isn't
implemented).

If/when move semantics comes to a compiler near you, the above program
will go to the heap only once, whether or not RVO is implemented.

1. To create the vector inside of foo.

The assignment will be a "move assignment", transferring resources from
the temporary (foo's return) to v. Any copies that are not elided away
in the call to foo will use vector's move constructor instead of
vector's copy constructor.

However if you would like to completely disable this optimization which
move semantics will give you, simply code:

const std::vector<int>
foo(unsigned n)
{
return std::vector<int>(n);
}

More sleep cycles anyone?

Although you can't take advantage of move semantics today, I believe you
will in the future. Coding const return values today is just planting
silent performance killers in tomorrow's code.

-Howard
 
Reply With Quote
 
Rolf Magnus
Guest
Posts: n/a
 
      01-06-2005
Gianni Mariani wrote:

> Derek wrote:
>> Some authors advocate returning const objects:
>>
>> const Point operator+(const Point&, const Point&);
>> ^^^^^
>>
>> Returning a const object prevents some bad code from compiling:
>>
>> Point a, b, c;
>> (a + b) = c; // error
>>
>> But it also prevents some potentially convenient constructs:
>>
>> Point a, b, c;
>> a = (b + c).normalize(); // error

>
> What's stopping you from creating a "const" version of normalize that
> returns a copy of a normalized Point ?
>
> i.e.
>
> class Point
> {
> .... blah ....
>
> Point & normalize();
> const Point normalize() const;
> };


You mean a non-const version that modifies the Point itself and a const
version that copies it and modifies the copy? Sounds quite unintuitive to
me. If you try to normalize a Point and didn't notice that that point is
const, your operation is just silently ignored.

 
Reply With Quote
 
Rolf Magnus
Guest
Posts: n/a
 
      01-06-2005
Howard Hinnant wrote:

> My vote is to ignore this convention. Good conventions prevent
> /accidental/ errors. When was the last time you saw something like this
> happen by accident:
>
> (a + b) = c; // error
>
> ?!
>
> I've never seen it happen. Otoh, I have personally used constructs like:
>
> a = (b + c).normalize();
>
> and would be frustrated if the return of op+ forced me to make a useless
> copy:
>
> a = Point(b + c).normalize();
>
> It would be more fun to just insert sleep cycles in my code. :-\


Actually, since you talk about additional copies: I would let functions like
normalize modify the object they were called for instead of making a copy
and then modifying that copy. If the user of the class wants the original
object to be modified, he will have to copy it back, like:

a = a.normalize();

Better let the user decide when he wants to copy the object.

 
Reply With Quote
 
Ivan Vecerina
Guest
Posts: n/a
 
      01-06-2005
"Derek" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Some authors advocate returning const objects:
>
> const Point operator+(const Point&, const Point&);
> ^^^^^
>
> Returning a const object prevents some bad code from compiling:
>
> Point a, b, c;
> (a + b) = c; // error


But the real question is: have you seen such an error
happen inadvertedly, or cause any bugs?
Does anyone have an example of an accidental error that
would have been prevented by returning a const type?

> But it also prevents some potentially convenient constructs:
>
> Point a, b, c;
> a = (b + c).normalize(); // error


With the vector library I use, I would write anyway:
a = unit(b+c); // works regardless...
I also have a 'normalize()' member function returning void,
but I do not like to mix mutating calls with accessor functions.

> The best argument I've heard to settle this standoff is that
> returning const objects makes them behave like built-in types:
>
> int x, y, z, w;
> x = (y + z) *= w; // error
>
> Are there any other compelling reasons to adopt/ignore this
> convention?


I'm fine regardless, but I would not bother using the more
verbose syntax if it cannot at least prevent some kind of
accidental error. In this case, it doesn't seem worth
the effort IMHO.

Cheers,
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form



 
Reply With Quote
 
Gianni Mariani
Guest
Posts: n/a
 
      01-07-2005
Rolf Magnus wrote:
> Gianni Mariani wrote:
>


....

>
> You mean a non-const version that modifies the Point itself and a const
> version that copies it and modifies the copy? Sounds quite unintuitive to
> me. If you try to normalize a Point and didn't notice that that point is
> const, your operation is just silently ignored.


Good point. (no pun intended) The idea in the previous post is dangerous.

Come to think of it, the most intuitive thing is that normalize returns
a copy of a normalized object. The whole idea of normalize is not too
different to unary minus which makes a copy. Another idea is to have 2
methods, normalize and normalize_self where normalize returns a copy and
normalize_self operates on the object itself.

G
 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      01-07-2005
Gianni Mariani wrote:
> [..]
> Come to think of it, the most intuitive thing is that normalize returns
> a copy of a normalized object. The whole idea of normalize is not too
> different to unary minus which makes a copy. Another idea is to have 2
> methods, normalize and normalize_self where normalize returns a copy and
> normalize_self operates on the object itself.


I'd say the const member should probably be named "get_normalized_copy" or
something the like. That's where style guides are often helpful. Longer
names should be used for functions that are used less often, probably. But
that's just IMHO.

V
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Const/non-const pointer returning method Jens Thoms Toerring C++ 11 05-26-2010 04:51 PM
is const necessary in eg int compar(const void *, const void *) lovecreatesbeauty@gmail.c0m C Programming 26 11-10-2008 09:47 PM
const correctness - should C++ prefer const member over non-const? fungus C++ 13 10-31-2008 05:33 AM
const vector<A> vs vector<const A> vs const vector<const A> Javier C++ 2 09-04-2007 08:46 PM
Casting int'** to 'const int * const * const' dosn't work, why? Jonas.Holmsten@gmail.com C Programming 11 07-01-2007 06:16 PM



Advertisments