1

const C++中函数参数的修饰符意味着此函数不能更改参数值,但不能保证函数在执行过程中不能被其他人更改。所以,编译器不能依赖数据不可变性进行任何优化。const rvalue引用是否允许对编译器进行额外优化?

据我所知,右值引用意味着给定的对象是暂时的,所以没有其他人可以访问其数据。在这种情况下,编译器可以进行攻击优化吗?

这将允许通过某种

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

(只是示例代码)有更快的代码,或者通过const&&传递值时,我们肯定不能被函数调用过程中改变。这是可能的,还是有一些未提及的问题?

+1

限定 – bolov

+0

这意味着在一些其他对象非const引用改变“别人改变。” – aaalex88

+0

看到我的答案。这有不同的场景。一个是“被另一个线程修改”,另一个是“被相同线程修改” – bolov

回答

4

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是非const引用)。

让我们返回之前增加一个函数调用代码:

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&添加到方程中并不会改变方程式。只能通过当前函数中调用的代码修改对象

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

据我所知右值引用是指给定的对象是暂时的, 让其他人访问其数据

事实并非如此。右值引用可以绑定到prvalues(临时)或xvalues。你自己的例子说明这一点:

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

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

乔纳森Wakely钉它在一篇评论:

你举的例子证明,常量牛逼& &不必绑定到一个 暂时的,有可能是绑定到 相同的几个右值引用事情:

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

所以这是对const&情况

无异

这里是我对吧:

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引用的对象被修改foo

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

+0

因此,由其他ref访问右值引用不是UB的标准?这是可悲的。 – aaalex88

+0

@ aaalex88它与const&'如何工作是一致的 – bolov