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?
Is it correct that returning a reference to a local variable is not a good idea?
Yes. The local object will be destroyed when get out of the function so the returned reference is always dangled.
You might make x
a static
variable.
record& get_record(int key) {
if (valid(key))
return lookup(key);
else {
static record x;
x.valid=false;
return x;
}
}
Note that the returned reference will always refer to the same object, i.e. x
.
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:
key
is valid return a reference to an existing/permanant object, andThose two are mutually exclusive, and your function doesn't make sense: what does get_record
return semantically?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With