10

In an programming interview I had yesterday, one of the programs I had to write ended up having something like this:

struct Blob
{
    // basic field containing image blob statistics.
};

std::vector<Blob> find_blobs (const Image& ...)
{
    std::vector<Blob> blobs;
    // ...
    return blobs;
}

I'm familiar with return value optimization (RVO), so I just mentioned that returning the vector would not cause a copy on popular compilers (there is a single return statement as the last line, and no control paths can return another object in the code I wrote).

However, the interviewer told me that since Blob may be a complex user defined type (UDT), the compiler may not be able to perform RVO. He further added that returning a std::vector<Blob*> would increase the chances that the compiler would perform the copy elision.

To the best of my understanding, the capacity the compiler has of performing RVO are completely irrelevant of the type of object being returned, save for non-copyable objects, for which the compiler will (should?) reject the code even if the resulting code could compile without ever invoking the copy constructor.

So, was the interviewer right? Can a complex return type prevent the compiler from applying RVO?

André Caron
  • 44,541
  • 12
  • 67
  • 125

1 Answers1

7

No, the types used should not affect the optimization.

The only reason I see to use pointers would be that they are cheaper to copy if the compiler fails the RVO. Not likely with the most popular compilers.

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
  • Indeed, should the compiler perform a copy, copying a vector of pointers would be cheaper (although in this case, `BLOB` was a POD with 2-3 fields of primitive types resulting in a slightly larger `memcpy()`). However, that would require explicit memory management on the part of the caller and I try to avoid that as much as possible. – André Caron Apr 06 '12 at 19:24
  • Yes, using pointer is not recommended unless you are forced to. Compilers like g++ perform this optimization even at the lowest optimization level, `-O0`. But I don't know what your potential employer(?) is using. ;-) – Bo Persson Apr 06 '12 at 19:28
  • Yeah, I think g++ always applies RVO unless you explicitly disable it using `-fno-elide-constructors`. MSVC 2008 performs it even in debug mode (I just verified with an example). AFAIK, this potential employer uses all popular compilers (well, at least g++ and MSVC). – André Caron Apr 06 '12 at 19:35
  • std::vector has a move constructor/assignment operator as well. If NRVO should fail, move constructor will be selected instead of copy constructor. https://stackoverflow.com/questions/11088023/is-an-object-guaranteed-to-be-moved-when-it-is-returned – Name Mar 15 '21 at 20:39