简体   繁体   中英

Returning a reference to a const stuct's (pointer-type) member: apparent lvalue to rvalue conversion

Given the following code, GCC gives some unexpected errors & warnings. I'm trying to return a member of a struct by reference, and it's saying that I'm returning a temporary! Also, when attempting to fix this function, it complains of a value category conversion error? In any case, as far as I know, a member access to a lvalue object should produce an lvalue, so this code should work in the first place. What is wrong?

Code: ( live on Coliru )

const struct {
    int* iptr = nullptr;
} cnst_struct;

const int* const& return_temporary_warning() {
    return cnst_struct.iptr;
}

const int*& value_cat_convert_error() {
    return cnst_struct.iptr;
}

Produces (GCC):

main.cpp: In function 'const int* const& return_temporary_warning()':
main.cpp:8:24: warning: returning reference to temporary [-Wreturn-local-addr]
     return cnst_struct.iptr;
                        ^~~~
main.cpp: In function 'const int*& value_cat_convert_error()':
main.cpp:16:24: error: cannot bind non-const lvalue reference of type 'const int*&' to an rvalue of type 'const int*'
     return cnst_struct.iptr;

            ~~~~~~~~~~~~^~~~

The code in question can be made to compile without errors or warnings by making the struct member a pointer-to-const:

const struct {
    const int* iptr = nullptr;
} cnst_struct;

Or, by making the functions return non-const references.

The issue here (while subtle) is that the iptr member is not the exact same type as the decayed type of the reference that is being returned, and so conversions are attempted. There is one, namely int* -> const int* but the result of this conversion is a rvalue, and hence all the warnings and errors.

Also, Clang produces a different warning, that is perhaps more helpful:

main.cpp:8:12: warning: returning reference to local temporary object [-Wreturn-stack-address]
    return cnst_struct.iptr;
           ^~~~~~~~~~~~~~~~
main.cpp:16:12: error: non-const lvalue reference to type 'const int *' cannot bind to a value of unrelated type 'int *const'
    return cnst_struct.iptr;
           ^~~~~~~~~~~~~~~~

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM