A return type changed from const Bar& getBar()
to const Bar getBar()
.
If i use:
const auto& bar = getBar();
and the return type changes. I have a reference on a temporary object.
If i use:
const auto bar = getBar();
i always make a copy of Bar
.
What is The best practice for this problem?
class Bar {
public:
Bar() = default;
Bar(const Bar&) = default;
Bar(Bar&&) = delete;
Bar& operator=(const Bar&) = delete;
Bar& operator=(const Bar&&) = delete;
void setValue(int i);
int value() const;
private:
int m_i = 0;
};
class Foo {
public:
Foo(Bar& bar) : m_bar(bar) {}
Foo(const Foo&) = delete;
Foo(Foo&&) = delete;
Foo& operator=(const Foo&) = delete;
Foo& operator=(const Foo&&) = delete;
const Bar& giveMeBar();
private:
Bar& m_bar;
};
int main() {
auto bar = std::make_unique<Bar>();
auto foo = std::make_unique<Foo>(*bar.get());
const auto& barFromFoo = foo->giveMeBar();
bar->setValue(2);
std::cout << "original bar: " << bar->value() << std::endl;
std::cout << "bar from foo: " << barFromFoo.value() << std::endl;
}
What is actually "best practice" is opinion based. I will only try to explain why your premise isn't sound so you can make up your opinion on what is a good practice yourself and/or can judge some guideline on the matter.
If i use:
const auto& bar = getBar();
and the return type changes. I have a reference on a temporary object.
The lifetime of the temporary is extended and bound to the constant reference. There is no problem. If you want to avoid an unnecessary copy then don't make a copy. In the shown code you can replace const Bar& giveMeBar();
with const Bar giveMeBar();
without any issues.
For illustration consider this example:
#include <iostream>
struct foo {
~foo(){ std::cout << "yes. I leave now. Bye\n";}
};
foo bar() { return foo{};}
int main() {
const foo& f = bar();
std::cout << "are you still there?\n";
}
are you still there?
yes. I leave now. Bye
PS: auto
does not change anything about that. The following are pairwise equivalent:
const auto& barFromFoo = foo->giveMeBar();
const Bar& barFromFoo = foo->giveMeBar(); // same
// and
const auto barFromFoo = foo->giveMeBar();
const Bar barFromFoo = foo->giveMeBar(); // same