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
153 views
in Technique[技术] by (71.8m points)

c++ - What is the point of returning a const alias from a function

Please look at the following code and help me understand: Why the functionality to return a const alias to a literal like my f2 function exists. I don't understand what the point is. The difference between f2 and f3 is that const does allow me to put a literal in the return statement, but again why?

Any help in understanding this is appreciated.

#include <iostream>

const int f1(int a)
{
    return 15;
}

const int& f2(int a)
{
    return 14;
}

int& f3(int a)
{
    a = 12;
    return a;
}

int main()
{

    auto a{ 10 };
    auto b = f1(a);
    auto c = f2(a);
    auto d = f3(a);

    std::cout << a << " " << b << " " << c << " " << d << std::endl;
    a = 1;
    b = 2;
    c = 3;
    d = 4;
    std::cout << a << " " << b << " " << c << " " << d << std::endl;
}

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

1 Reply

0 votes
by (71.8m points)

Both f2 and f3 have undefined behaviour. You are returning references to local variables. Those local variables are destroyed when the function ends, and the reference is dangling.

The difference between a const reference, and a non-const reference is that a const reference can bind to both rvalues and lvalues.

For non-const references you have to distinguish between lvalue-reference(int&) and rvalue-reference(int&&).

So using the function signature int&& f2(int a) would also compile, but equally have undefined behaviour.

The main reason this is usefull is because when we pass a reference to a function, the function signature tell us if we are expecting an lvalue or an rvalue. We can also overload both and decide to move/copy depending on what we get.

In the case where we don't care, or if we only want to read from the value we can use a const reference and be able to accept both lvalues and rvalues that are passed in.

void foo(MyClass& mc) {
    // We know mc is an lvalue.
    // We could copy mc, or modify it if we want to use it as an output parameter.
}

void foo(MyClass&& mc) {
    // We know mc is an rvalue.
    // We know it would be safe to move from mc in this case.
}

MyClass mc;
foo(mc); // Callsthe first overload
foo(MyClass{}); // Calls the second overload

// The two functions above can be overloaded, so we can make sure we deal
// with both cases in the right way

void foo2(const MyClass& mc) {
    // This can be both an rvalue or lvalue.
    // We don't really care since the reference
    // is const we are only going to read from it.
}

foo2(mc); // Both calls work
foo2(MyClass{});

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

...