【问题标题】:Bind rvalue reference to lvalue with `void*`使用 `void*` 将右值引用绑定到左值
【发布时间】:2018-09-30 21:13:11
【问题描述】:

在尝试了解右值引用的工作原理时,我最终得到了这段代码:

int* iptr = nullptr;
int*&& irr = iptr;

编译上面的代码会报如下错误:

错误:对类型“int *”的右值引用无法绑定到类型的左值 'int *'

我理解这是正确的,但为什么下面的代码(我使用void* 而不是int* 绑定)编译没有任何问题?运行时行为是正确的还是我应该期待未定义的行为?

int* iptr = nullptr;
void*&& irr = iptr;

【问题讨论】:

    标签: c++ c++11 language-lawyer rvalue-reference lvalue


    【解决方案1】:

    这是格式正确的。

    int*void* 是不同的类型;您不能直接将int* 绑定到对void* 的引用。 int* 需要先转换为void*,这是一个临时对象,可以绑定到右值引用。 (PS 临时的生命周期延长到引用的生命周期。)

    注意irr 不绑定到iptr;所以对它的任何修改都与iptr无关。

    这对于void* 并不特殊,其他类型也会发生同样的情况,例如

    char c;
    int&& r = c; // a temporary int is constructed from c and then bound to r;
                 // its lifetime is extened to the lifetime of r
    

    【讨论】:

      【解决方案2】:

      除了@songyuanyao 回答:你可以用iptr 做一个右值,例如通过static_cast:

        int* iptr = nullptr;
        int*&& irr = static_cast<int *>(iptr);
      

      【讨论】:

      • 为什么不只是std::move
      • @songyuanyao 因为移动实际上会将irr 绑定到iptr
      • 如果您发现static_cast 很笨重,请知道int *&amp;&amp;irr = +iptr; 做同样的事情:)
      • @Nick 表示irr 引用(允许访问)iptr 本身。对于演员表,irr 指的是演员表的未命名结果(其生命周期延长到与irr 一样长),它是iptr 的副本。
      • @Quentin 你是对的。事实证明,在这种情况下,prvalue 的寿命会延长 - 但 xvalue 的寿命不会延长。
      猜你喜欢
      • 2017-12-06
      • 2014-10-31
      • 2017-04-13
      • 2014-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多