繁体   English   中英

成员函数引用限定的返回类型

[英]Member function reference qualified return type

读迈耶斯的新书,我发现与此非常相似:

// compile with
// g++-4.8 --std=c++11 -Wall   main3.cc && ./a.out
#include <iostream>
#include <vector>

class Widget
{
    public:
        using DType = std::vector<int>;


        DType& data() &  // lvalue
          { 
            std::cout << "data (lvalue)    : " << &data_[0] << std::endl; 
            return data_; 
          };

        DType data() &&  //  rvalue
          { 
            std::cout << "data (rvalue)    : " << &data_[0] << std::endl; 
            return std::move(data_);  
          }; 

        // Please Note
        // int parameter is here to make the overloading possible
        // in a single class
        DType&& data(int) && 
          { 
            std::cout << "data (rvalue ref): " << &data_[0] << std::endl; 
            return std::move(data_);  
          }; 
    private:
        DType data_ { 0 };
};

Widget getWidget() { return Widget(); }


int main(int argc, char *argv[])
{
    Widget w1;
    std::vector<int> d1 = w1.data();
    std::cout << "d1 copied        : " << &d1[0] << std::endl;

    std::vector<int> d2 = getWidget().data();
    std::cout << "d2 moved         : " << &d2[0] << std::endl;

    std::vector<int> d3 = getWidget().data(0);
    std::cout << "d3 moved         : " << &d3[0] << std::endl;

    return 0;
}

我的意思很简单:我希望能在盒子上得到这些结果

data (lvalue)    : 0x8e28008
d1 copied        : 0x8e28018
data (rvalue)    : 0x8e28028
d2 moved         : 0x8e28028
data (rvalue ref): 0x8e28038
d3 moved         : 0x8e28038

因此,在复制第二个和第三个向量的同时复制了第一个向量。

您可以使用两种不同的签名来实现移动操作:

一个返回右值

DType data() &&  //  rvalue

和一个重现右值引用

DType&& data() && 

他们达到了相同的结果:我看不到任何区别吗? 什么是“最好”的?

您可以使用两种不同的签名来实现移动操作:

那是错的。

第一个签名(返回DType )执行到返回值的移动。 第二个签名,一个返回DType&&签名,仅返回一个引用。 它什么也没动。

此移动发生在其他代码中,特别是std::vector<int> d3 = 从xvalue初始化向量将执行移动。 那就是移动的方向,而不是功能。 但是 ,其他类型的操作不会执行以下操作:

// no move, just binding the member to a reference
std::vector<int>&& d3 = getWidget().data(0);

但是,使用第一个函数,总是会发生移动:

// move into a temporary, and bind *that* to a reference
std::vector<int>&& d2 = getWidget().data();

第二个签名很危险。 意外地将引用返回给它很容易。 在您认为某些内容已移出但没有移出的地方,很容易编写误导性的客户端代码。 一个明智的用例返回右值引用,该用例已经由标准库以std::movestd::forward

暂无
暂无

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

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