Reputation: 649
const
modifier for function parameter in C++ means that this function can't change parameter value, but doesn't guarantee that it can't be changed by someone else during function execution. So, compiler can't do any optimizations relying on data immutability.
As I understand rvalue reference means that given object is temporary, so nobody else have access to its data. Can compiler make aggresive optimizations in this case?
It would allow to have faster code through some kind of
template<class T>
class Immutable
{
private:
const T val;
public:
operator const T && () { return std::move(val); }
};
(just sample code), or passing values by const&&
when we sure they can't be changed during function call. Is it possible, or there are some unmentioned problems?
Upvotes: 0
Views: 472
Reputation: 75688
tl'dr: It doesn't enable any optimization as it doesn't guarantee in any way the object is not modified. It only adds confusion. Don't use it!
First we need to clarify what "changed by someone else" means.
by another thread. In this case your question is not aplicabile. You need to protect your data with a mutex
or other mechanism. Otherwise the compiler can assume that no other thread modifies the data.
same thread, in a code not called (directly or indirectly) by the function. Not possible.
same thread, in a code called (directly or indirectly) by the function.
We will obviously deal with the last one:
Lets' take a simple code and look at the assembly (-O3
)
auto foo(int& a)
{
a = 24;
return a;
}
foo(int&): # @foo(int&)
mov dword ptr [rdi], 24
mov eax, 24
ret
As you can see mov eax, 24
. The returned value is set to 24
. This means that the compiler can assume that no other code can modify the object referenced by a
(even when a
is a non-const reference).
let's add a function call code before the return:
auto bar() -> void;
auto foo(int& a)
{
a = 24;
bar();
return a;
}
foo(int&): # @foo(int&)
push rbx
mov rbx, rdi
mov dword ptr [rbx], 24
call bar()
mov eax, dword ptr [rbx]
pop rbx
ret
The compiler doesn't have access to the body of bar
and so it has to take into account that bar
could modify the object referenced by a
.
Now adding const&
into the equation as per your question doesn't change the equation. The object could be modified only by code called within the current function.
Having const&&
doesn't change this in any way. The object referenced by a
can still be modified.
As I understand rvalue reference means that given object is temporary, so nobody else have access to its data
Not true. An rvalue reference can be bound to prvalues
(temporaries) or xvalues
. Your own example shows this:
operator const T && () { return std::move(val); }
here you bound to val
which is not a temporary (if the enclosing object is not).
Jonathan Wakely nailed it in a commentary:
Your example proves that const T&& doesn't have to be bound to a temporary, and there could be several rvalue references bound to the same thing:
Immutable<int> i{}; const int&& r1 = i; const int&& r2 = i;
So This is no different to the
const&
case
And here is my take on it:
int g = 24;
auto bar() -> void { g = 11; };
auto foo(const int&& a)
{
bar();
return a;
}
auto test()
{
return foo(std::move(g));
}
test(): # @test()
mov dword ptr [rip + g], 11
mov eax, 11
ret
The above code is valid1) and it shows that the object referenced by the const int&&
parameter a
is modified during the call of foo
.
1) although I am not 100% sure, I am fairly certain
Upvotes: 5