【问题标题】:Understanding reference binding了解引用绑定
【发布时间】:2015-07-02 14:28:45
【问题描述】:

我们不能将非 const 左值引用绑定到右值,但它可以绑定到 const 引用。我们也不能将右值引用绑定到左值。实际上标准是这样说的:

8.5.3/5.2:

引用应该是对非易失性常量的左值引用 类型(即 cv1 应为 const),或者引用应为右值引用。

但有没有比“标准这么说”更好的解释?

【问题讨论】:

    标签: c++ reference


    【解决方案1】:

    因为它没有语义意义。

    您不能将非常量左值引用绑定到右值,因为修改右值意味着什么?根据定义,没有其他东西会看到结果,所以这没有意义。

    int& i = 3;
    //should change referenced location, but we aren't referencing a memory location
    i = 5; 
    

    您不能将右值引用绑定到左值,因为存在右值引用以促进对其引用对象的破坏性优化。你不希望你的物品被随意地从你的脚下移出,所以标准不允许这样做。

    void process_string (std::string&&);
    std::string foo = "foo";
    //foo could be made garbage without us knowing about it
    process_string (foo); 
    //this is fine
    process_string (std::move(foo));
    

    【讨论】:

    • 你不能简单地解释一下破坏性优化是什么......没有遇到过这个概念。
    • 看看move semantics。解释它们有点超出这个问题的范围,但这会帮助你理解我的意思。
    • 简短版是:移动操作,与复制操作不同,允许做一些事情,使其源对象处于“破坏”状态,只能被破坏。例如,如果您有一个内部具有指向某些私有数据的指针的对象,那么要复制该对象,您必须复制该数据。但是要移动它,移动目标可以简单地接管指向存储的指针,并在源对象中留下一个nullptr。对源的进一步操作是未定义的(此时其他成员可能没有意义),但析构函数仍应正确清理它。
    【解决方案2】:

    想想一些真实的案例:

    #include <vector>
    
    void f1( int& i ){i = 1;}
    void f2( const int& i ){i = 1;}
    void f3( std::vector<int>&& v ){auto v_move{v};}
    
    int main()
    {
        f1(3); // error: how can you set the value of "3" to "1"?
        f2(3); // ok, the compiler extend the life of the rvalue "into" f2
        std::vector<int> v{10};
        f3(v); // error: an innocent looking call to f3 would let your v very different from what you would imagine
        f3(std::vector<int>{10}); // ok, nobody cares if the rvalue passed as an argument get modified
    }
    

    【讨论】:

      猜你喜欢
      • 2012-08-02
      • 1970-01-01
      • 2010-09-20
      • 2012-02-16
      • 2017-05-03
      • 2011-07-19
      • 1970-01-01
      • 2023-02-24
      • 2016-06-09
      相关资源
      最近更新 更多