Search code examples
c++referencetemporary

How to create a temporary variable in C++


I have a function returning a reference to an instance of my class "record".

record& get_record(int key) {
    return lookup(key);
}

That is effective it returns a reference and not by value. Now I modify it a bit.

record& get_record(int key) {
    if (valid(key))
        return lookup(key);
    else {
        record x;
        x.valid=false;
        return x; //Here I really want to return a temporary variable
                  // and not a reference to a local variable.      
    }
}

Is it correct that returning a reference to a local variable is not a good idea? and how do I return x in such a way that it becomes a temporary variable?


Solution

  • This is worse than a bad idea, it is undefined behavior and result in most of the cases to a crash. This is bad (TM).

    What you could do is changing the return type of get_record so it returns a smart pointer. If key is valid, it returns an observer pointer to it. Otherwise, it returns an owning smart pointer to a freshly created object:

    #include <memory>
    #include <iostream>
    
    struct record { int n; } some_record{42};
    
    std::shared_ptr<record> get_record(bool b)
    {
        if (b == true) {
            return std::shared_ptr<record>{&some_record, [](record*){}}; // see explanation ^1
        }
        return std::shared_ptr<record>{new record{0}};
    }
    
    int main()
    {
        std::cout << get_record(true)->n << "\n";  // this is some_record
        std::cout << get_record(false)->n << "\n"; // this is a temporary
    }
    

    1) About [](record*){}: this no-op lambda given as the second argument to std::shared_ptr::shared_ptr() is invoked when the smart pointer is destroyed. It replaces the default deleter of std::shared_ptr whose behavior is to call delete on the owned pointer.


    About why your design is flawed. In fact, making get_record return a reference makes it not consistent. What you want is:

    • if key is valid return a reference to an existing/permanant object, and
    • return a temporary object otherwise.

    Those two are mutually exclusive, and your function doesn't make sense: what does get_record return semantically?