Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Best practice: return by value versus const ref

Reply
Thread Tools

Best practice: return by value versus const ref

 
 
Pavel
Guest
Posts: n/a
 
      10-07-2012
Nobody wrote:
> On Fri, 05 Oct 2012 17:33:44 +0200, Marcel Müller wrote:
>
>> taking into account that many (almost all?) std::string implementations
>> provide a copy constructor with O(1) together with copy on write,

>
> Not any more. That used to be common until multi-threading started
> being widely used, at which point the overhead of locking every access
> outweighed the advantages of CoW. It might still be used on platforms
> which have separate single-threaded and multiple-threaded versions of the
> standard library. But in general, you should assume that string copies are
> O(n).
>

Just FYI: GNU STL's std::string is COW, for both single- and multi- threaded
compilations; and have been for quite a while since multi-threading became common.

-Pavel
 
Reply With Quote
 
 
 
 
goran.pusic@gmail.com
Guest
Posts: n/a
 
      10-08-2012
On Friday, October 5, 2012 2:32:15 PM UTC+2, Mikewhy wrote:
> Apologies. I know this has to have been discussed, but I'm unable to google
>
> my way past the shallower, newbie discussions of temporary's lifetime, etc.
>
>
>
> A class Lookup contains a collection of strings referenced by some key, the
>
> values representing, perhaps, a database lookup.. The key is representative
>
> of its field name. Here, we're interested only in the accessor methods,
>
> get_val() and get_value(). The first returns a copy of the string by value.
>
> The other returns a const reference to the value.
>
>
>
> class Lookup
>
> {
>
> public:
>
> enum FieldId {
>
> ...
>
> };
>
>
>
> std::string get_val(FieldId) const;
>
>
>
> const std::string & get_value(FieldId) const;
>
> ...
>
> };
>
>
>
> The values already exist as std::string in the Lookup object. Returning by
>
> const reference then is direct and has the advantage of efficiency.
>
> Returning by value, even with return value optimization, incurs at minimum a
>
> string copy.
>
>
>
> The question is, assuming that multithread issues are not present, how
>
> easily can naive code cause trouble for itself with a const reference return
>
> interface? What usage patterns (that have a chance of surviving the low
>
> threshold of a peer review) might prove problematic?


Except from what Rui Maciel had shown, I can only think of a subsequent change:

class v1
{
type field;
public:
const type& getfield() const { return field; }
};

class v2 // v1, but code changed in the meantime
{
type calculated() { return type(...); }
public:
const type& getfield() const { return calculated(); }
};

This will produce at least a diagnostic when compiled ("returning a reference to a temporary" or some such), so well-cranked up warning level is beneficial...

At any rate, the core issue is the same here and in the other example: one took a reference to something, and that something ceased to exist.

As for your question "how easily can naive code?"... Hard to say. It depends very much on people working on the code. The less experience, the more chance there is this will happen and vice verso.

Goran.

P.S. random rambler on the 'net once said: "OOP in C++ means "Object Ownership Protocols" .
 
Reply With Quote
 
 
 
 
none
Guest
Posts: n/a
 
      10-08-2012
In article <k4mk0e$lg7$(E-Mail Removed)>,
Mikewhy <(E-Mail Removed)> wrote:
>Apologies. I know this has to have been discussed, but I'm unable to google
>my way past the shallower, newbie discussions of temporary's lifetime, etc.
>
>A class Lookup contains a collection of strings referenced by some key, the
>values representing, perhaps, a database lookup.. The key is representative
>of its field name. Here, we're interested only in the accessor methods,
>get_val() and get_value(). The first returns a copy of the string by value.
>The other returns a const reference to the value.
>
>class Lookup
>{
>public:
> enum FieldId {
> ...
> };
>
> std::string get_val(FieldId) const;
>
> const std::string & get_value(FieldId) const;
> ...
>};
>
>The values already exist as std::string in the Lookup object. Returning by
>const reference then is direct and has the advantage of efficiency.
>Returning by value, even with return value optimization, incurs at minimum a
>string copy.
>
>The question is, assuming that multithread issues are not present, how
>easily can naive code cause trouble for itself with a const reference return
>interface? What usage patterns (that have a chance of surviving the low
>threshold of a peer review) might prove problematic?


My concerns are similar to Goran. You are painting yourself in a
corner for future refactoring.

you are stating that the Lookup class does have a member variable for
every one of the FieldId that can be queried. That is now. However,
for something like a "Lookup", it would seem plausible that you may
not forever want to keep a cache of all data in the object. The
interface you present forces you to do it forever in order to possibly
save a few CPU cycles (which have not been profiled as being
critical).

Note also that a client that uses the interface as follow may gain a
small performance improvement:

std::string const & value = aLookup.get_value(FieldId);

However, a client that attempt to use it as follow:
(a very common way to write)

std::string value = aLookup.get_value(FieldId);

may very much be less performant that if you'd return by value.

Anyone that want to di into the details of what RVO and Copy Elision
my mean in optimized code should read through Dave Abrahams article:
http://cpp-next.com/archive/2009/08/...pass-by-value/

and this article is not even C++11 aware.

Yannick




 
Reply With Quote
 
Mikewhy
Guest
Posts: n/a
 
      10-09-2012
"none (Yannick Tremblay)" wrote in message
news:k4uesg$8ak$(E-Mail Removed)...

In article <k4mk0e$lg7$(E-Mail Removed)>,
Mikewhy <(E-Mail Removed)> wrote:
>Apologies. I know this has to have been discussed, but I'm unable to google
>my way past the shallower, newbie discussions of temporary's lifetime, etc.
>
>A class Lookup contains a collection of strings referenced by some key, the
>values representing, perhaps, a database lookup.. The key is representative
>of its field name. Here, we're interested only in the accessor methods,
>get_val() and get_value(). The first returns a copy of the string by value.
>The other returns a const reference to the value.
>
>class Lookup
>{
>public:
> enum FieldId {
> ...
> };
>
> std::string get_val(FieldId) const;
>
> const std::string & get_value(FieldId) const;
> ...
>};
>
>The values already exist as std::string in the Lookup object. Returning by
>const reference then is direct and has the advantage of efficiency.
>Returning by value, even with return value optimization, incurs at minimum
>a
>string copy.
>
>The question is, assuming that multithread issues are not present, how
>easily can naive code cause trouble for itself with a const reference
>return
>interface? What usage patterns (that have a chance of surviving the low
>threshold of a peer review) might prove problematic?


My concerns are similar to Goran. You are painting yourself in a
corner for future refactoring.

you are stating that the Lookup class does have a member variable for
every one of the FieldId that can be queried. That is now. However,
for something like a "Lookup", it would seem plausible that you may
not forever want to keep a cache of all data in the object. The
interface you present forces you to do it forever in order to possibly
save a few CPU cycles (which have not been profiled as being
critical).

Note also that a client that uses the interface as follow may gain a
small performance improvement:

std::string const & value = aLookup.get_value(FieldId);

However, a client that attempt to use it as follow:
(a very common way to write)

std::string value = aLookup.get_value(FieldId);

may very much be less performant that if you'd return by value.
================

Sure. Point taken about copy construction versus. It's a slightly different
context, but certainly one of the differences that I had asked for.

The actual usage that led to my OP is illustrated by (but not actually):

if (foo[field1] == "VALUE1" ||
foo[field1] == "VALUE2 ||
(foo[field1] == "VALUE3 &&
foo[field4] == "VALUE4"))
{ ... }


 
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
why is binding non-const ref to return value bad? PeteUK C++ 9 03-12-2010 11:41 AM
Re: Mozilla versus IE versus Opera versus Safari Peter Potamus the Purple Hippo Firefox 0 05-08-2008 12:56 PM
equal? versus eql? versus == versus === verus <=> Paul Butcher Ruby 12 11-28-2007 06:06 AM
Is this legal? assigning return value to a const ref? flopbucket C++ 10 10-31-2007 06:11 PM
const vector<A> vs vector<const A> vs const vector<const A> Javier C++ 2 09-04-2007 08:46 PM



Advertisments