const 右值引用是否允许对编译器进行额外优化?
Does const rvalue references allow extra optimisations for compiler?
const
C++中函数参数的修饰符表示该函数不能改变参数值,但不保证在函数执行过程中不能被其他人改变。因此,编译器无法依赖数据不变性进行任何优化。
据我了解,右值引用意味着给定对象是临时的,因此没有其他人可以访问其数据。编译器可以在这种情况下进行积极的优化吗?
它可以通过某种
来获得更快的代码
template<class T>
class Immutable
{
private:
const T val;
public:
operator const T && () { return std::move(val); }
};
(只是示例代码),或者当我们确定它们在函数调用期间不能更改时通过 const&&
传递值。有可能吗,还是有一些没有提到的问题?
tl'dr:它不启用任何优化,因为它不以任何方式保证对象未被修改。它只会增加混乱。 不要使用它!
首先我们需要弄清楚"changed by someone else"是什么意思。
来自另一个线程。在这种情况下,您的问题不适用。您需要使用 mutex
或其他机制来保护您的数据。否则编译器会假定没有其他线程修改数据。
同一个线程,在函数未调用(直接或间接)的代码中。不可能。
同一线程,在函数调用(直接或间接)的代码中。
我们显然会处理最后一个:
让我们看一段简单的代码,看看程序集(-O3
)
auto foo(int& a)
{
a = 24;
return a;
}
foo(int&): # @foo(int&)
mov dword ptr [rdi], 24
mov eax, 24
ret
如您所见mov eax, 24
。 returned 值设置为 24
。这意味着编译器可以假定没有其他代码可以修改 a
引用的对象(即使 a
是非常量引用)。
让我们在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
编译器无法访问 bar
的主体,因此它必须考虑到 bar
可以修改 a
.[=39 引用的对象=]
现在根据您的问题将 const&
添加到等式中不会改变等式。只能通过在当前函数中调用的代码修改对象。
拥有 const&&
不会以任何方式改变这一点。 a
引用的对象仍然可以修改。
As I understand rvalue reference means that given object is temporary,
so nobody else have access to its data
不正确。右值引用可以绑定到 prvalues
(临时)或 xvalues
。您自己的示例显示了这一点:
operator const T && () { return std::move(val); }
这里你绑定到 val
这不是临时的(如果封闭对象不是)。
Jonathan Wakely 在评论中指出:
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
这是我的看法:
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
上面的代码是有效的1)并且表明const int&&
参数a
所引用的对象在[=的调用过程中被修改了36=].
1)虽然我不是100%确定,但我相当确定
const
C++中函数参数的修饰符表示该函数不能改变参数值,但不保证在函数执行过程中不能被其他人改变。因此,编译器无法依赖数据不变性进行任何优化。
据我了解,右值引用意味着给定对象是临时的,因此没有其他人可以访问其数据。编译器可以在这种情况下进行积极的优化吗?
它可以通过某种
来获得更快的代码template<class T>
class Immutable
{
private:
const T val;
public:
operator const T && () { return std::move(val); }
};
(只是示例代码),或者当我们确定它们在函数调用期间不能更改时通过 const&&
传递值。有可能吗,还是有一些没有提到的问题?
tl'dr:它不启用任何优化,因为它不以任何方式保证对象未被修改。它只会增加混乱。 不要使用它!
首先我们需要弄清楚"changed by someone else"是什么意思。
来自另一个线程。在这种情况下,您的问题不适用。您需要使用
mutex
或其他机制来保护您的数据。否则编译器会假定没有其他线程修改数据。同一个线程,在函数未调用(直接或间接)的代码中。不可能。
同一线程,在函数调用(直接或间接)的代码中。
我们显然会处理最后一个:
让我们看一段简单的代码,看看程序集(-O3
)
auto foo(int& a)
{
a = 24;
return a;
}
foo(int&): # @foo(int&)
mov dword ptr [rdi], 24
mov eax, 24
ret
如您所见mov eax, 24
。 returned 值设置为 24
。这意味着编译器可以假定没有其他代码可以修改 a
引用的对象(即使 a
是非常量引用)。
让我们在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
编译器无法访问 bar
的主体,因此它必须考虑到 bar
可以修改 a
.[=39 引用的对象=]
现在根据您的问题将 const&
添加到等式中不会改变等式。只能通过在当前函数中调用的代码修改对象。
拥有 const&&
不会以任何方式改变这一点。 a
引用的对象仍然可以修改。
As I understand rvalue reference means that given object is temporary, so nobody else have access to its data
不正确。右值引用可以绑定到 prvalues
(临时)或 xvalues
。您自己的示例显示了这一点:
operator const T && () { return std::move(val); }
这里你绑定到 val
这不是临时的(如果封闭对象不是)。
Jonathan Wakely 在评论中指出:
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
这是我的看法:
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
上面的代码是有效的1)并且表明const int&&
参数a
所引用的对象在[=的调用过程中被修改了36=].
1)虽然我不是100%确定,但我相当确定