C++: returning by reference and copy constructors

后端 未结 9 1776
伪装坚强ぢ
伪装坚强ぢ 2020-12-09 09:46

References in C++ are baffling me. :)

The basic idea is that I\'m trying to return an object from a function. I\'d like to do it without returning a pointer (because

相关标签:
9条回答
  • 2020-12-09 10:21

    About the only time it makes sense to return a reference is if you're returning a reference to a pre-existing object. For an obvious example, nearly every iostream member function returns a reference to the iostream. The iostream itself exists before any of the member functions is called, and continues to exist after they're called.

    The standard allows "copy elision", which means the copy constructor doesn't need to be called when you return an object. This comes in two forms: Name Return Value Optimization (NRVO) and anonymous Return Value Optimization (usually just RVO).

    From what you're saying, your compiler implements RVO but not NRVO -- which means it's probably a somewhat older compiler. Most current compilers implement both. The un-matched dtor in this case means it's probably something like gcc 3.4 or thereabouts -- though I don't remember the version for sure, there was a one around then that had a bug like this. Of course, it's also possible that your instrumentation isn't quite right, so a ctor that you didn't instrument is being used, and a matching dtor is being invoked for that object.

    In the end, you're stuck with one simple fact though: if you need to return an object, you need to return an object. In particular, a reference can only give access to a (possibly modified version of) an existing object -- but that object had to be constructed at some point as well. If you can modify some existing object without causing a problem, that's fine and well, go ahead and do it. If you need a new object different and separate from those you already have, go ahead and do that -- pre-creating the object and passing in a reference to it may make the return itself faster, but won't save any time overall. Creating the object has about the same cost whether done inside or outside the function. Any reasonably modern compiler will include RVO, so you won't pay any extra cost for creating it in the function, then returning it -- the compiler will just automate allocating space for the object where it's going to be returned, and have the function construct it "in place", where it'll still be accessible after the function returns.

    0 讨论(0)
  • 2020-12-09 10:22

    One potential solution, depending on your use case, is to default-construct the object outside of the function, take in a reference to it, and initialize the referenced object within the function, like so:

    void initFoo(Foo& foo) 
    {
      foo.setN(3);
      foo.setBar("bar");
      // ... etc ...
    }
    
    int main() 
    {
      Foo foo;
      initFoo(foo);
    
      return 0;
    }
    

    Now this of course does not work if it is not possible (or does not make sense) to default-construct a Foo object and then initialize it later. If that is the case, then your only real option to avoid copy-construction is to return a pointer to a heap-allocated object.

    But then think about why you are trying to avoid copy-construction in the first place. Is the "expense" of copy construction really affecting your program, or is this a case of premature optimization?

    0 讨论(0)
  • 2020-12-09 10:22

    Not a direct answer, but a viable suggestion: You could also return a pointer, wrapped in an auto_ptr or smart_ptr. Then you'll be in control of what constructors and destructors get called and when.

    0 讨论(0)
提交回复
热议问题