0

I've just begun using c++ and I was wondering if there was some guideline around when to do the following:

Let's say I want to return a struct or object. Which of these approaches would be better under what circumstances?

void PopulateStruct(MyStruct* struct) {
      struct->a = x;
      struct->b = y;
}

void Caller() {
    MyStruct s;
    PopulateStruct(&s);
}

OR:

MyStruct PopulateStruct() {
    MyStruct s;
    s.a = x;
    s.b = y;
    return s;
}

void Caller() {
    MyStruct s = PopulateStruct();
}

My basic understanding is that if the struct / object is pretty small then the latter option is probably fine (better?) since the copy will be fast and compilers might also use RVO to avoid an actual copy.

And perhaps if the object is really large then you want the former to avoid that copy?

Atul Bhatia
  • 1,633
  • 5
  • 25
  • 50
  • I would be surprised if any modern compiler didn't take advantage of RVO and NRVO at every available opportunity. So in that respect I think the latter method is more semantically reasonable and understandable. – Cory Kramer Aug 02 '17 at 18:20
  • [Return Value Optimization](http://en.cppreference.com/w/cpp/language/copy_elision) is mandatory/implicit in many cases now. – François Andrieux Aug 02 '17 at 18:21
  • Possible dupe: https://stackoverflow.com/questions/33994995/which-is-more-efficient-return-a-value-vs-pass-by-reference – NathanOliver Aug 02 '17 at 18:22
  • [This video](https://www.youtube.com/watch?v=q0N9Tvf7Bz0&list=PLHTh1InhhwT7J5jl4vAhO1WvGHUUFgUQH&index=108) does show some interesting edge cases. – NathanOliver Aug 02 '17 at 18:25
  • If the variable is local, you can't return by reference or pointer because the variable ceases to exist after execution leaves the function. – Thomas Matthews Aug 02 '17 at 18:27
  • Indeed -- added the return statement. – Atul Bhatia Aug 02 '17 at 18:52

2 Answers2

1

According to the CppCoreGuidelines by Herb Sutter and Bjarne Stroustrup, the second example is the recommended way. It makes reasoning on the code easier and does not force you to create uninitialized objects in some situations.

See guideline F.20.

A return value is self-documenting, whereas a & could be either in-out or out-only and is liable to be misused.

Galik
  • 47,303
  • 4
  • 80
  • 117
  • Completely agree about the readability (which was the motivation behind asking this question). I was curious about the performance aspect, and it seems like both scenarios should be equally performant with most compilers – Atul Bhatia Aug 02 '17 at 18:43
  • @AtulBhatia For many years now most compilers optimize the return by creating the object in the caller's stack segment. The C++ standards specifically allow for that optimization. – Galik Aug 02 '17 at 18:50
0

In modern compilers, returning an object can be done with move semantics, and even without move semantics it would be fast enough.

It depends on whether you want scope destruction to be applied or you want the programmer to take care of the ownership of the object you are returning.

lilezek
  • 6,976
  • 1
  • 27
  • 45