4

I don't have a feeling (yet, I hope) for whether to chose value or reference semantics in some situations. Is there any rule of thumb I can apply?

I usually pick references for everything other than the built-in data types (char, int, bool, double etc.). However, sometimes it's not possible to return references from a function, so I would have to use pointers. The following function is an example of this:

Foo bar()
{
    Foo f;
    f.do_stuff();
    return f;
}

I'd use boost::shared_ptr to store the Foo object, but it makes working with the object quite ugly. I'm currently looking at a function that returns a deque that will hardly ever have more than 10 elements (that's what I assume, I have no way of making sure). Would it be OK to return this by value? Are my considerations a case of premature optimization?

Neo
  • 67
  • 3
  • possible duplicate of [How to pass objects to functions in C++?](http://stackoverflow.com/questions/2139224/how-to-pass-objects-to-functions-in-c) – fredoverflow Dec 12 '10 at 12:24

5 Answers5

3

In any case, don't return anything allocated on the stack (i.e. local variable, such as f here) by reference or pointer.

fredoverflow
  • 256,549
  • 94
  • 388
  • 662
Ofir
  • 8,194
  • 2
  • 29
  • 44
  • 1
    @Alex: because it's allocated on the stack so when the function returns that stack based variable is deallocated and your pointer or reference becomes invalid. – sashang Dec 12 '10 at 12:26
  • @sashang: The wording is unclear (and even wrong). It should be "don't return anything ...". I downvote, and will cancel the downvote provided @Ofir edits its answer. – Alexandre C. Dec 12 '10 at 12:26
  • @Alexandre: because after your function finishes, the object will be destroyed with the stack frame, so you end up with a dangling pointer. – Vlad Dec 12 '10 at 12:27
  • 1
    @Alex: I think it's pretty clear Ofir meant returning, so I edited the answer. – fredoverflow Dec 12 '10 at 12:41
3

Returning by value is fine, since most compilers will optimize the extra copy away (this is called Return Value Optimization, or rather Named Return Value Optimization in your case).

But the idiomatic way is

void bar(Foo& out)
{
   out.do_stuff();
}
Alexandre C.
  • 55,948
  • 11
  • 128
  • 197
  • 2
    @fhd: There are two drawbacks with this approach though: you have to make sure that `out` is in the state you want it to be, and it is more cumbersome to type (and less natural). I usually go with returning by value and rely on the NRVO. – Alexandre C. Dec 12 '10 at 12:30
  • @fhd: There is however an advantage with this approach, is that you don't construct the object inside the function, so you get rid of a possible construction failure which could break exception safety. – Alexandre C. Dec 12 '10 at 12:33
0

You could always do this:

Foo& bar(Foo& f)
{
    f.do_stuff();
    return f;
}

And use it like this:

Foo f;
bar(f);

The drawback here is that you can't guarantee that bar() will receive a fresh copy of a Foo object. If that's important, you'll have to modify it to this:

Foo& bar(Foo& f)
{
    f = Foo();
    f.do_stuff();
    return f;
}

But then there will be an unnecessary initialization if it does get a fresh copy. Alternatively, you could simply examine f before doSomething() and throw an exception if it isn't up to expectations.

suszterpatt
  • 8,187
  • 39
  • 60
0

Use a reference when you want to maintain the state of any variable or object (i.e reurning the same variable to the calling routine after some procesisng has been done on the variable/object by the called routine) and also in case of passing large data to the function else there will be double copy of the large volumed data.

Also in some where copying of objects bit wise needs to be prevented, in such cases we make the copy constructor of a class as private.

Arunmu
  • 6,837
  • 1
  • 24
  • 46
-1

My normal rules are:

  1. always use pass by value.

    Simple, eh? Reference suck. They should never have been introduced.

  2. If you have a "value like data structure" pass it. If you have an "object like data structure" pass a pointer (reference semantics, pass by value).

    It's usually clear what kind of thing a type is: value or object. If you can mutate it, its an object.

Yttrill
  • 4,725
  • 1
  • 20
  • 29