繁体   English   中英

将右值引用绑定到VC ++中的局部变量

[英]Binding rvalue-reference to a local variable in VC++

我正在使用VC ++ 2012运行以下代码:

#include <utility>

struct A
{
    int* m_p;

    A() { m_p = new int; }
    ~A() { delete m_p;  }

    A(const A& otherA)
    {
        m_p = new int;

        // BOOM!
        *m_p = *otherA.m_p;
    }
};

A&& CreateA()
{
    A a;
    return std::move(a);
}

int _tmain(int argc, _TCHAR* argv[])
{
    A a2 = CreateA();
    return 0;
}

在创建a2 A的过程中,其复制ctor称为-并崩溃,因为在CreateA()中创建的源对象已被销毁。 这是标准行为吗? 这可能是编译器错误吗?

请注意,如果将a2的类型从“ A”更改为“ const A&”,则不会发生崩溃-这使人们更加怀疑它确实是一个错误。 谁能对此有所启发?

注意:我完全知道这不是rvalue-refs的预期用途,并且该示例是人为设计的。 只是希望能更好地了解这种新型行为。

您不能访问超出其范围的局部变量 右值引用不会改变这一点:它们仍然是引用。 所提供的代码具有未定义的行为,因为它返回对局部变量的引用,然后对其进行访问。

不要返回右值引用。 绝大多数时间都是愚蠢的。 而是返回值:

A CreateA()
{
    A a;
    return a; // a move here is automatic
              // unless you are using a compiler with outdated rules like MSVC
    //return std::move(a); // ok, poor MSVC
    // alternatively:
    //return A{}; //or 
    //return A();
}

当你写A const& a2 = CreateA(); 没有崩溃,因为您实际上没有访问任何对象。 您要做的只是获取一个悬而未决的参考书。 但是,此代码的格式甚至不正确,只是因为MSVC对于引用绑定有一些过时的规则,所以恰好可以编译。

因此,基本上,这些行为是编译器错误和未定义行为的混合:)

查看代码中发生的情况:

  1. CreateA()被调用
  2. 在函数内部,将创建一个类型为A的局部变量。
  3. 您创建一个指向该局部变量的右值引用
  4. 您返回此右值引用
  5. 当您返回时,右值引用所指向的类型为A的对象超出范围并被销毁
  6. 现在参考指向被破坏的物体
  7. 您尝试将a2初始化为该函数调用中曾经存在的对象的副本

还有...那是行不通的。 您要复制的对象已消失。 未定义的行为。

不要那样做 :)

在C ++中,引用不会影响所引用对象的生存期。 没有“我要指向该对象,因此您无法销毁它!”。

切勿返回对本地对象的引用。 它不起作用,所以...只是不这样做。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM