Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
257 views
in Technique[技术] by (71.8m points)

c++ - Why not always assign return values to const reference?

Let's say I have some function:

Foo GetFoo(..)
{
  ...
}

Assume that we neither know how this function is implemented nor the internals of Foo (it can be very complex object, for example). However we do know that function is returning Foo by value and that we want to use this return value as const.

Question: Would it be always a good idea to store return value of this function as const &?

const Foo& f = GetFoo(...);

instead of,

const Foo f = GetFoo(...);

I know that compilers would do return value optimizations and may be move the object instead of copying it so in the end const & might not have any advantages. However my question is, are there any disadvantages? Why shouldn't I just develop muscle memory to always use const & to store return values given that I don't have to rely on compiler optimizations and the fact that even move operation can be expensive for complex objects.

Stretching this to extreme, why shouldn't I always use const & for all variables that are immutable in my code? For example,

const int& a = 2;
const int& b = 2;
const int& c = c + d;

Besides being more verbose, are there any disadvantages?

question from:https://stackoverflow.com/questions/37649236/why-not-always-assign-return-values-to-const-reference

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

These have semantic differences and if you ask for something other than you want, you will be in trouble if you get it. Consider this code:

#include <stdio.h>

class Bar
{
    public:
    Bar() { printf ("Bar::Bar
"); }
    ~Bar() { printf ("Bar::~Bar
"); }
    Bar(const Bar&) { printf("Bar::Bar(const Bar&)
"); }
    void baz() const { printf("Bar::Baz
"); }
};

class Foo
{
    Bar bar;

    public:
    Bar& getBar () { return bar; }
    Foo() { }
};

int main()
{
    printf("This is safe:
");
    {
        Foo *x = new Foo();
        const Bar y = x->getBar();
        delete x;
        y.baz();
    }
    printf("
This is a disaster:
");
    {
        Foo *x = new Foo();
        const Bar& y = x->getBar();
        delete x;
        y.baz();
    }
    return 0;
}

Output is:

This is safe:
Bar::Bar
Bar::Bar(const Bar&)
Bar::~Bar
Bar::Baz
Bar::~Bar

This is a disaster:
Bar::Bar
Bar::~Bar
Bar::Baz

Notice we call Bar::Baz after the Bar is destroyed. Oops.

Ask for what you want, that way you're not screwed if you get what you ask for.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...