c++ - 成员函数引用限定返回类型

标签 c++ c++11

阅读迈耶斯的新书我发现了一些与此非常相似的东西:

// 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

因此第一个 vector 被复制,而第二个和第三个被移动。

可以有两个不同的签名来实现移动操作:

一个返回一个右值

DType data() &&  //  rvalue

还有一个返回右值引用

DType&& data() && 

他们取得了相同的结果:是否有任何我看不到的差异?什么是“最好的”?

最佳答案

You can have two different signature to achieve move operation:

这是错误的。

第一个签名,返回的那个DType , 执行返回值的移动。第二个签名,返回的那个DType&&只是返回一个引用。它不会移动任何东西。

移动发生在其他代码中,特别是带有 std::vector<int> d3 = 的部分.从 xvalue 初始化 vector 执行移动。那就是移动,而不是功能。 但是,其他类型的操作不会执行移动:

// 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::move 的形式处理了该用例。和 std::forward .

关于c++ - 成员函数引用限定返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24737191/

相关文章:

java - 在什么情况下网络爬虫可能会受到 CPU 限制而不是 IO 限制?

c++ - 我如何在客户端支持多个版本的 TLS?

c++ - 将一种类型的 std::vector 转换为另一种类型

c++ - 使用 lambda 函数定义运算符

带线程的 C++ 类 - 析构函数、构造函数、 move 构造函数?

c++ - 如何判断 stderr 是否已在 Windows 中重定向?

c++ - 计算没有循环 C++ 的数字位数

c++ - 使用 ifstream 在 while 循环中将数据传递给 vector

c++ - 将 c++11 之前的设置函数更改为带有转发功能的现代模板化函数是个好主意吗

c++ - Stringstream编译错误只出现在linux环境下