直观的理解功能,参考参考文献

可能重复:
T &&在C ++ 11中意味着什么?

出于某种原因,这是逃避我的直觉,我无法在互联网上找到任何解释。 对于一个C ++函数来说,引用一个引用是什么意思? 例如:

void myFunction(int&& val);     //what does this mean?!

我明白通过引用传递的想法,所以

void addTwo(int& a)
{
    a += 2;
}

int main()
{
    int x = 5;
    addTwo(x);

    return 0;
}

工作,对我来说很直观。


这不是引用的引用,而是称为右值引用的新语言特征,它表示(非正式)对内存中的对象的引用,该对象在程序中的其他位置未引用,并且可以进行破坏性修改。 例如,函数的返回值可以通过右值引用捕获,临时值也可以引入到表达式中。

右值引用可以用于各种目的。 从大多数C ++程序员的角度来看,他们可以用来实现移动语义,从而可以通过将旧对象的内容“移出”旧对象并将其转换为新对象来初始化新对象。 您可以使用它从C ++ 11中的函数中返回大对象,而无需花费巨额的代价来复制对象,因为用于捕获返回值的对象可以使用移动构造函数初始化,只需从临时对象中窃取内部元素由return语句创建。

移动语义与复制语义是正交的,所以对象可以移动而不可复制。 例如, std::ofstream s不可复制,但它们将是可移动的,因此您可以使用移动行为从函数返回std::ofstream s。 目前无法在C ++ 03中完成。 例如,这个代码在C ++ 03中是非法的,但在C ++ 11中是非常好的(并且被鼓励!):

std::ifstream GetUserFile() {
    while (true) {
        std::cout << "Enter filename: ";
        std::string filename;
        std::getline(std::cin, filename);

        ifstream input(filename); // Note: No .c_str() either!
        if (input) return input;

        std::cout << "Sorry, I couldn't open that file." << std::endl;
    }
}

std::ifstream file = GetUserFile(); // Okay, move stream out of the function.

直观地说,一个采用右值引用的函数是(可能)试图通过将旧对象的内容移动到新对象中来避免昂贵的副本的函数。 例如,您可以通过让该构造函数接受右值引用来为向量类对象定义移动构造函数。 如果我们将向量表示为指向数组的指针的三元组,数组的容量和已用空间,我们可以实现其移动构造函数,如下所示:

vector::vector(vector&& rhs) {
    /* Steal resources from rhs. */
    elems    = rhs.elems;
    size     = rhs.size;
    capacity = rhs.capacity;

    /* Destructively modify rhs to avoid having two objects sharing 
     * an underlying array.
     */
    rhs.elems    = nullptr; // Note use of nullptr instead of NULL
    rhs.size     = 0;
    rhs.capacity = 0;
}

重要的是要注意到,当我们在构造函数的最后清除rhs时,我们最终将rhs置于这样的状态

  • 它的析构函数调用时不会导致崩溃(注意我们将它的元素指针设置为nullptr ,因为释放nullptr是安全的),并且
  • 仍然让对象分配一个新的值。 后一点很棘手,但确保您仍然可以在某个时间给清除的对象一个新的值很重要。 这是因为可以获得一个对象的右值,这个对象在程序后面仍然可以被引用。
  • 为了说明(2),右值引用的一个有趣的用例是在对象之间显式移动值的能力。 例如,考虑swap这种惯用实现:

    template <typename T> void swap(T& lhs, T& rhs) {
        T temp = lhs;
        lhs = rhs;
        rhs = temp;
    }
    

    这段代码是合法的,但有点不寻常。 特别是,它最终制作三份 - 首先将temp设置为等于lhs的副本,一次将lhs设置为rhs的副本,并将rhs设置为temp的副本。 但我们真的不想在这里制作任何副本; 相反,我们只是想调整价值观。 因此,在C ++ 11中,您可以使用std::move函数显式地获取对象的右值引用:

    template <typename T> void swap(T& lhs, T& rhs) {
        T temp = std::move(lhs);
        lhs = std::move(rhs);
        rhs = std::move(temp);
    }
    

    现在,根本没有拷贝。 我们将lhs的内容移动到temp ,然后将rhs的内容移动到lhs ,然后将temp内容移动到rhs 。 在这样做的过程中,我们暂时将lhsrhs置于“空”状态,然后再添加新的值。 编写代码以将内容移出对象时,我们必须将对象保留在某种格式良好的状态,以便此代码正常工作。

    希望这可以帮助!


    这不是对参考的参考。 这是C ++ 0x中为所谓的Rvalue引用引入的新语法。

    链接地址: http://www.djcxy.com/p/40467.html

    上一篇: Intuitive understanding of functions taking references of references

    下一篇: Angular binding object with array from component to view with ngModels