代码之家  ›  专栏  ›  技术社区  ›  user3816764

如何获得对右值的引用?

  •  9
  • user3816764  · 技术社区  · 9 年前

    我用过 std::move std::forward 在C++中。我的问题是:标准库实际上是如何实现这些功能的?

    如果左值是您可以获取地址的值,并且右值不是唯一的左值,那么如何实际实现这些引用?

    这些新设施是否允许:

    auto x = &(3); 
    

    或者类似的东西?你能引用一个不只是 std::移动 / forward 返回左值?

    希望这些问题有意义。我在谷歌上找不到好的信息,只有完美转发的教程等。

    3 回复  |  直到 9 年前
        1
  •  11
  •   Mike Seymour    9 年前

    如何获得 右值 ?

    从概念上讲 右值 表达式创建临时对象,或有时表示现有对象。它可以像任何其他对象一样绑定到引用;但是,为了避免混淆,语言只允许 右值 const 左值 参考文献。

    我在C++中使用了std::move和std::forward。我的问题是编译器如何实际实现这一点?

    move 简单地返回 右值 对其参数的引用,相当于

    static_cast<typename remove_reference<T>::type&&>(t)
    

    函数调用的结果是 右值 (具体而言 x值 ),因此它可以绑定到 右值 函数参数不能的引用。这允许您从 左值 ,使用 移动 将其转换为 右值 ,同时不允许您意外移动。

    forward 类似,但重载以返回 右值 引用 右值 右值 参考,和 左值 引用任何其他内容。

    如果l值是某个值,则可以获得

    这或多或少是正确的。官方的定义是“指定一个函数或一个对象”,这些都是有地址的东西。

    并且r值不是l值

    不是真的。稍微简化一下,表达式可以是 左值 右值 ,但可以从一个转换为另一个。一 左值 可以隐式转换为 右值 ; 转换另一种方式可以通过一个演员来完成,如 移动

    如何实际实现这些引用?

    就像任何其他引用一样-作为它绑定到的对象的别名或指针。唯一的区别是可以使用哪种表达式来表示(并可能创建)绑定到引用的对象。

    这些新设施是否允许 auto x = &(3);

    试图获取 右值 直接,这是不允许的。由于问题是关于引用,而不是指针,因此允许将引用绑定到临时对象(其生存期被延长以匹配引用):

    auto && rvalue = 3;
    auto const & const_lvalue = 3;
    

    而不允许将其绑定到非常量 左值 参考

    auto & lvalue = 3;  // ERROR
    
        2
  •  5
  •   Lightness Races in Orbit Shash316    9 年前

    我无法调用函数: void foo(string* bar) 这样地: foo(&string("Hello World!")) 或者我得到一个错误:

    错误:获取临时地址

    我也不能调用函数: void foo(string& bar) 这样地: foo(string("Hello World!")) 或者我得到一个错误:

    错误:“std::string&”类型的非常量引用的初始化无效;{aka std::basic_string&}”类型的右值

    C++11为我提供了一个右值引用的能力,所以我 可以 调用函数: void foo(string&& bar) 这样地: foo(string("Hello World!"));

    此外,在内部 foo 可以 获取右值引用传入的对象的地址:

    void foo(string&& bar){
        string* temp = &bar;
    
        cout << *temp << " @:" << temp << endl;
    }
    

    OP似乎对右值有很好的把握。但是 this explanation of them 对我有帮助,也可能对其他人有帮助。它详细介绍了为什么C++03允许对右值的常量引用,而不是C++11的右值引用。

        3
  •  1
  •   MSalters    9 年前

    基本上,编译器的魔力。标准描述了规则,编译器制造商只需要弄清楚如何实现规则。

    实际上,引用要么被优化,要么被实现为CPU级别的指针。

    std::move 在这个意义上并不特别。它有一个左值引用作为输入,一个右值引用作为输出。编译器只需将右值引用规则应用于输入即可。

    同样 std::forward<T> 只是告诉编译器将一组不同的规则应用于参数,这些规则恰好被定义为完美的转发。函数本身不起作用。