相关文章推荐
才高八斗的茶叶  ·  Single sign-on ...·  3 周前    · 
烦恼的水桶  ·  _invalid_parameter, ...·  5 天前    · 
失落的汽水  ·  Building a Real-Time ...·  昨天    · 
发怒的卤蛋  ·  將 Azure Boards 或 ...·  1 年前    · 
失眠的灭火器  ·  vue+element ...·  2 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

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?

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.

Great answer. Just to add, you should be careful about leaks in such function if you are using new. You should wrap them in auto_ptr or shared_ptr to prevent yourself making careless leaks. – lxcid Apr 14, 2011 at 17:44

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.

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!
                Or maybe you want to return it by value.  That's usually the case (but it obviously depends on the semantics of AnotherObject).
– James Kanze
                Apr 14, 2011 at 17:33
                return new AnotherObject() doesn't work.  I get an error: invalide initialization reference of type 'const AnotherObject&' from expression of type 'AnotherObject*'
– dcinadr
                Apr 14, 2011 at 18:21
                If you want to return a pointer, then the return type becomes AnotherObject *, just like the error message says.
– Blindy
                Apr 15, 2011 at 2:29

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.

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.

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; 

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.