Dan*_*iel 12 c++ pass-by-reference rvalue-reference c++11
可能重复:
T &&在C++ 11中意味着什么?
出于某种原因,这是在逃避我的直觉,我在互联网上找不到任何解释.C++函数引用引用是什么意思?例如:
void myFunction(int&& val); //what does this mean?!
Run Code Online (Sandbox Code Playgroud)
我理解传递引用的想法,所以
void addTwo(int& a)
{
a += 2;
}
int main()
{
int x = 5;
addTwo(x);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
工作,对我来说很直观.
tem*_*def 33
这不是引用的引用,而是一种称为右值引用的新语言特性,它表示(非正式地)对内存中对象的引用,该引用未在程序中的其他地方引用,并且可以被破坏性地修改.例如,函数的返回值可以通过右值引用捕获,引入表达式的临时值也可以捕获.
Rvalue引用可用于各种目的.从大多数C++程序员的角度来看,它们可用于实现移动语义,从而可以通过将旧对象的内容"移动"出旧对象并进入新对象来初始化新对象.您可以使用它来从C++ 11中的函数返回大型对象,而无需花费巨大的成本来复制对象,因为用于捕获返回值的对象可以使用移动构造函数通过从临时对象中窃取内部来初始化由return语句创建.
移动语义与复制语义正交,因此对象可以移动而不可复制.例如,std::ofstreams不可复制,但它们是可移动的,因此您可以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.
Run Code Online (Sandbox Code Playgroud)
直观地,采用右值引用的函数是(可能)通过将旧对象的内容移动到新对象中来试图避免昂贵的副本的函数.例如,您可以通过使构造函数接受右值引用来为类向量对象定义移动构造函数.如果我们将向量表示为指向数组的指针的三元组,数组的容量和使用的空间,我们可以实现其移动构造函数,如下所示:
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;
}
Run Code Online (Sandbox Code Playgroud)
重要的是要注意,当我们rhs在构造函数的最后清除时,我们最终会rhs进入这样的状态
nullptr,因为释放nullptr是安全的),并且为了阐明(2),rvalue引用的一个有趣用例是在对象之间显式移动值的能力.例如,考虑以下惯用实现swap:
template <typename T> void swap(T& lhs, T& rhs) {
T temp = lhs;
lhs = rhs;
rhs = temp;
}
Run Code Online (Sandbox Code Playgroud)
这段代码是合法的,但有点不寻常.特别是,它最终会制作三个副本 - 首先设置temp等于副本lhs,一次设置lhs为副本rhs,一次设置rhs为副本temp.但我们真的不想在这里制作任何副本; 相反,我们只是想改变周围的价值观.因此,在C++ 11中,您将能够使用以下std::move函数显式获取对象的rvalue引用:
template <typename T> void swap(T& lhs, T& rhs) {
T temp = std::move(lhs);
lhs = std::move(rhs);
rhs = std::move(temp);
}
Run Code Online (Sandbox Code Playgroud)
现在,根本没有制作副本.我们将内容lhs移入temp,然后将内容rhs移入lhs,然后将内容temp移入rhs.在此过程中,我们都离开lhs,并rhs暂时把新的值到他们之前在"清空"状态.重要的是,在编写代码时将内容移出一个对象,我们将对象保持在一个格式良好的状态,以便此代码正常工作.
希望这可以帮助!