Handling Type Changes with auto in C++

82 Views Asked by At

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;
}
1

There are 1 best solutions below

0
463035818_is_not_an_ai On BEST ANSWER

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";    
}

Output:

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