0

Consider the following function that returns a big object:

std::list<SomethingBig> DoSomething()
{
    std::list<SomethingBig> TheList;
    //do stuff
    return TheList;
}

I want to get the list, not a copy of it. Because if I have to copy such objects, the performance price is expensive. I know return-value optimization may take care of this for me, but depending on optimizations to optimize bad code is not the best way to go (right?).

A clean way to avoid copying and extend the life of an object, is using a constant reference (and please test it before calling it a dangling reference, because it's not):

const std::list<SomethingBig>& theList = DoSomething();

In C++11, one could use std::move to avoid copying. However, I'm working on a C++03 program, and I have to do this:

const std::list<SomethingBig>& list1 = DoSomething();
const std::list<SomethingBig>& list2 = DoSomethingElse();

and now I need to splice the lists together. The only way for me to do that is either copy everything, or const_cast these lists and splice them. Is there a better solution?

The Quantum Physicist
  • 24,987
  • 19
  • 103
  • 189

2 Answers2

1

Just return it by value, it would be better than both reference and std::move due to NRVO, which is not an "optimization of a bad code", but a way to make good code work fast.

As far as I know NRVO is indeed not guaranteed to happen (as opposed to RVO, which will be a must since c++17), but it's extremely unlikely the compiler will not elide a copy here.

In any case, relying on copy elision is much safer than using const_cast tricks, and it's cheaper than a move.

Both clang and gcc elide the copy with -std=c++03 -O0

Ap31
  • 3,244
  • 1
  • 18
  • 25
0

What about changing interface of DoSomething...() to std::list<SomethingBig> & DoSomething(std::list<SomethingBig> &)? The life time of the list object would be controlled outside of DoSomething() and DoSomethingElse(). e.g.:

std::list<SomethingBig> list;
DoSomethingElse(DoSomething(list));