Q
Q
Qubc2021-08-10 16:16:32
C++ / C#
Qubc, 2021-08-10 16:16:32

Why can't return object by value in non-const &?

https://godbolt.org/z/dqTffoGPn

In assembly code, when calling a struct sf ( void ) function that returns an object by value, the memory for the object is actually allocated inside the main() stack frame beforehand. The address of this object is secretly passed to the function, and the object is not created inside the function. Very cool.

But do I understand correctly that the ban on returning "object by value" in a non-const reference is a purely syntactic rule, and not a technical limitation?

spoiler

const reference или const & термины полностью отражают суть механизма и они используются в англ. книгах.
Верно ли я понимаю, что перевод "ссылка на константу" совсем ошибочен, потому что "константа" это вообще другая история?
Верно ли, что правильно говорить "ссылка на объект с const квалификатором" ?
Верно ли, что не совсем правильно, но короче говорить "ссылка на константный объект" ?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
W
Wataru, 2021-08-10
@Qubc

The first is Retrun Value Optimization. The compiler sees that the result of the function is used to initialize the variable and instead of allocating memory for a temporary object and copying it immediately fills the result.
About the link. The result of the function in your case is prvalue
in the same link, it says:

An rvalue may be used to initialize a const lvalue reference , in which case the lifetime of the object identified by the rvalue is extended until the scope of the reference ends.
An rvalue may be used to initialize an rvalue reference , in which case the lifetime of the object identified by the rvalue is extended until the scope of the reference ends.

Those. it is prohibited by the standard to initialize a non-const reference through a prvalue.
Why is it done? Because these same prvalue / rvalue are essentially temporary objects. You can't take an address from them, they don't have a name, the compiler can put them anywhere and destroy them right after the current expression.
If it were possible to make a reference to these temporary objects and somehow change them later, this would complicate the analysis and the possibility of some optimizations. Like for example RVO in your question. I would have to create a temporary variable in main to store the result, because the function does not allocate memory for the result. Therefore, this is not in the C++ standard.
Then, when rvalue references were introduced in C++11 and the categories of values ​​were shoveled, it was allowed to initialize rvalue references through prvalue.
That's why they work
const int& r1 = f();
int&& r2 = f();

M
Mercury13, 2021-08-10
@Mercury13

const struct s & ref = f();
This mechanism is called "prolonging the life of a temporary object."
You can write like this. The main reason for converting a temporary object to only const T& and T&& is subtle errors in function superposition. Namely, in no case should we pass a temporary object to a function that accepts s&.
struct s && ref = f();

void modify(s& arg) { ++arg[1]; }

...

modify(f());

We called the f() function, passed its result to modify, and… fucked it up.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question