【问题标题】:Does const rvalue references allow extra optimisations for compiler?const rvalue 引用是否允许对编译器进行额外优化?
【发布时间】:2017-02-24 08:08:15
【问题描述】:

constC++中的函数参数修饰符表示该函数不能改变参数值,但不保证在函数执行过程中不能被其他人改变。因此,编译器无法根据数据不变性进行任何优化。

据我了解,右值引用意味着给定对象是临时的,因此没有其他人可以访问其数据。在这种情况下编译器可以进行积极的优化吗?

它将允许通过某种方式获得更快的代码

template<class T>
class Immutable 
{ 
private: 
    const T val; 
public: 
    operator const T && () { return std::move(val); } 
};

(只是示例代码),或者通过const&amp;&amp; 传递值,当我们确定它们在函数调用期间无法更改时。有没有可能,还是有一些未提及的问题?

【问题讨论】:

  • 定义“被别人改变”
  • 表示被其他对象中的非常量引用改变了。
  • 看我的回答。有不同的场景。一个是“被另一个线程更改”,另一个是“被同一线程更改”
  • 您的示例证明const T&amp;&amp; 不必绑定到临时对象,并且可能有多个右值引用绑定到同一事物:Immutable&lt;int&gt; i{}; const int&amp;&amp; r1 = i; const int&amp;&amp; r2 = i;。所以这与const&amp; 的情况没有什么不同。

标签: c++ optimization constants compiler-optimization rvalue-reference


【解决方案1】:

tl'dr:它不会启用任何优化,因为它不能以任何方式保证对象不会被修改。它只会增加混乱。 不要使用它!


首先我们需要澄清一下“被别人改变”是什么意思。

  • 由另一个线程。在这种情况下,您的问题不适用。您需要使用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。返回值设置为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 引用的对象。

现在根据您的问题将const&amp; 添加到等式中不会改变等式。 只能通过在当前函数中调用的代码来修改对象

拥有const&amp;&amp; 不会以任何方式改变这一点。 a 引用的对象仍然可以修改。

据我了解,右值引用意味着给定对象是临时的, 所以没有其他人可以访问其数据

不正确。右值引用可以绑定到prvalues(临时)或xvalues。您自己的示例显示了这一点:

operator const T && () { return std::move(val); } 

在这里你绑定到val 这不是临时的(如果封闭对象不是)。

Jonathan Wakely 在评论中指出:

您的示例证明 const T&& 不必绑定到 临时的,并且可能有多个右值引用绑定到 同样的事情:

Immutable<int> i{};
const int&& r1 = i;
const int&& r2 = i;

所以这与const&amp; 的情况没有什么不同

这是我的看法:

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&amp;&amp;参数a引用的对象在foo的调用过程中被修改了。

1) 虽然我不是 100% 确定,但我相当确定

【讨论】:

  • 那么,通过其他 ref 访问右值引用不是标准的 UB 吗?很难过。
猜你喜欢
  • 1970-01-01
  • 2015-02-28
  • 1970-01-01
  • 2019-08-03
  • 2018-12-30
  • 2021-03-19
  • 1970-01-01
  • 2019-04-21
  • 1970-01-01
相关资源
最近更新 更多