How to return references to object created inside a method

我的梦境 提交于 2020-01-13 10:35:07

问题


I am reasoning about the best approach to return references to objects created inside a method, like in the following situation:

class A{
public:
    A(){}
    ~A(){}
};

class Foo{
public:
    Foo(){}
    ~Foo(){}
    A& create(int random_arg){
         // create object A and return its reference
    }
};

void other_method(){
     Foo f;
     A a = f.create();
     // do stuff with a
{

I have considered three possible solutions:

  1. create a raw pointer and return a reference, but this is bad because there is no guarantee that the object will be properly deleted:

    A& create(int random_arg){
         A* a = new A();
         return *a;
    }
    
  2. create a shared_ptr and return the shared_ptr by value. In this way the shared_ptr will take care of the object deletion:

    shared_ptr<A> create(int random_arg){
         boost::shared_ptr<A> a_ptr(new A());
         return a_ptr;
    }
    
  3. create a shared_ptr and return a reference:

    A& create(int random_arg){
         boost::shared_ptr<A> a_ptr(new A());
         return *a_ptr;
    }
    

The second solution seems to be the most used, but in this way I have to spread shared_ptr in the application and I would prefer to have references, or better const references.

What do you think is the best way to handle this situation? Are there other possibilities I have not considered?


回答1:


Don't do this. You're most likely to have a dangling reference.

Just return the instance of A by value instead.

It's likely that the compiler will elide the implied object copy. But you can guarantee that an object copy will not be made by writing a move constructor for A.




回答2:


The reason returning pointers or references to locals is a bad idea is the fact they are typically on a stack, which means the moment the stack reaches that depth again, the data will be overwritten and corrupted.

Newbies often make such mistakes, reassured by the fact it will often happen to work by pure luck, i.e. when you directly use the returned pointer before any other function has been called to corrupt the stack frame of the previous one.

Returning by value might be applicable in many cases, the compiler is free to optimize the return. But even without an optimization it might not be a big deal, for example in Qt all containers and many other classes do implicit sharing of resources, so returning by copy doesn't really copy all the data, just the shell of the object, usually a single pointer to the actual data. There is also move semantics in C++ which is sort of similar in that regard - it will move the responsibility from the local to the returned object without doing a deep copy.

There are two main cases where returning by value is not desired.

  • if it involves an unavoidable copy of a heavy object
  • if it is an object with "identity" - such have their copy constructor and assignment operators disabled, so they can't really be returned by value

In those cases you simply allocate the object dynamically and return a pointer to it. Whether you manage it manually or prefer to use a smart pointer - that's up to your needs.




回答3:


To complete Bathsheba's answer:

There is only one case where you might want to do something like that, that is if you are returning an instance to a singleton. In this case such instance will be a static object:

A& getTheOnlyInstanceOfA()
{
   static A onlyInstOfA;
   return onlyInstOfA; 
}


来源:https://stackoverflow.com/questions/29011496/how-to-return-references-to-object-created-inside-a-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!