C++ Returning reference to temporary [duplicate]

穿精又带淫゛_ 提交于 2019-12-30 06:04:08

问题


Possible Duplicate:
warning: returning reference to temporary

I am getting the error "returning reference to temporary" on the second line below.

class Object : public std::map <ExString, AnotherObject> const {
public:
const AnotherObject& Find (const ExString& string ) const {
  Object::const_iterator it = find (string);
  if (it == this->end()) { return AnotherObject() };
  return ( it->second );
}
}

My class implements std::map.

I am new to C++ so I'm guessing its just a syntax error. Any help?


回答1:


If your function looks like this:

AnotherObject& getAnotherObject()
{

    . . .

    Object::const_iterator it = find ("lang");
    if (it == this->end()) { return AnotherObject() };

    . . .

}

the problem is that the AnotherObject() you've returned will be destroyed as soon as the function exits, and so the caller to your function will have a reference to a bogus object.

If your function returned by value however:

AnotherObject getAnotherObject()

then a copy will be made before the original is destroyed and you'll be OK.




回答2:


return AnotherObject(); creates an object which is destroyed before function exit - temporaries are destroyed at the end of the expression that contains them[*], and the expression AnotherObject() creates a temporary.

Since the function returns by reference, this means that by the caller even gets a chance to see that reference, it no longer refers to a valid object.

It would be OK if the function were to return by value, since the temporary would be copied[**].

[*] With a couple of situations that don't, but they don't help you here.

[**] Actually there's an optimization called "copy constructor elision" which means the temporary needn't be created, copied and destroyed. Instead, under certain conditions the compiler is allowed to just create the target of the copy in the same way it would have created the temporary, and not bother with the temporary at all.




回答3:


You're creating a temporary value on the stack AnotherObject() and returning it right before it gets destroyed. Your function's caller would get garbage, and so it's forbidden.

Maybe you want to allocate it on the heap and return a pointer to it instead?

return new AnotherObject();

Alternatively, declare your function to return a "copy" to your object, instead of a reference like I'm assuming you are returning right now:

AnotherObject f()
{
  return AnotherObject();  // return value optimization will kick in anyway!
}



回答4:


The function must be declared to return a reference, and a reference has to refer to an object that will continue to exist after the function exits. Your temporary "AnotherObject()" is destructed right after the return, so that obviously won't work. If you can't change the method signature, you may need to throw an exception instead of returning an error value.




回答5:


You should change the return type of your function from "AnotherObject&" to "AnotherObject" and return that object by value. Otherwise it will go just like Blindy described




回答6:


You shouldn't return a reference to a temporary which is destroyed at the end of the line, nor a reference to a local which is destroyed at the end of the function.

If you want to keep the current signature, you'd have to add a static constant instance that you can return as a default.

#include <iostream>

template <class T>
class X
{
    T value;
    static const T default_instance;
public:
    X(const T& t): value(t) {}
    const T& get(bool b) const
    {
        return b ? value : default_instance;
    }
};

template <class T>
const T X<T>::default_instance = T();

int main()
{
    X<int> x(10);
    std::cout << x.get(true) << ' ' << x.get(false) << '\n';
}

You may also return by value or return a pointer in which case you can return NULL.




回答7:


The call to AnotherObject's constructor creates a new instance on the stack, which is immediatly destroyed when the method returns.

It is most likely not a good idea to create and return new object if the find fails. The calling code will have no way to tell if the object returned is a previously existing object present in the data structure.

If you do want to do this, then you should add the new object to the data structure and then return an iterator pointing to the new object IN THE DATA STRUCTURE.

Something like this:

if (it == this->end()) {
    it = this->insert(pair<ExString, AnotherObject>( string, AnotherObject() ));
    return  it->second; 
}    



回答8:


I personally think that this is a bit of a hack, but as long as you really stick to the const'ness of the returned reference you should be able to return a statically constructed instance of AnotherObject whose only "raison d'etre" is to be the "not found" return value of your function. Make it a static const private member of your class Object for example, and you should be ok as long as a default constructed instance of AnotherObject is not a valid value to be contained in an instance of Object.



来源:https://stackoverflow.com/questions/5667161/c-returning-reference-to-temporary

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