2、new_values.push_back( 2 * *itr ); 11. } 12. return new_values; 13.} 14. 15.int main() 16.{ 17. vector v; 18. for ( int i = 0; i < 100; i++ ) 19. { 20. v.push_back( i ); 21. } 22. v = doubleValues( v ); 23.} 先来分析一下上述代码的运行过程。1.ve
3、ctor v; 2.for ( int i = 0; i < 100; i++ ) 3.{ 4. v.push_back( i ); 5.} 以上5行语句在栈上新建了一个vector的实例,并在里面放了100个数。1.v = doubleValues( v ) 这条语句调用函数doubleValues,函数的参数类型的constreference,常量引用,那么在实参形参结合的时候并不会将v复制一份,而是直接传递引用。所以在函数体内部使用的v就是刚才创建的那个vector的实例。但是1.vector new
4、_values( v.size() ); 这条语句新建了一个vector的实例new_values,并且复制了v的所有内容。但这是合理的,因为我们这是要将一个vector中所有的值翻倍,所以我们不应该改变原有的vector的内容。1.v = doubleValues( v ); 函数执行完之后,new_values中放了翻倍之后的数值,作为函数的返回值返回。但是注意,这个时候doubleValue(v)的调用已经结束。开始执行=的语义。赋值的过程实际上是将返回的vector复制一份放入新的内存空间,然后改变v的地址,让v指向这篇内
5、存空间。总的来说,我们刚才新建的那个vector又被复制了一遍。但我们其实希望v能直接得到函数中复制好的那个vector。在C++11之前,我们只能通过传递指针来实现这个目的。但是指针用多了非常不爽。我们希望有更简单的方法。这就是我们为什么要引入右值引用和转移构造函数的原因。左值和右值在说明左值的定义之前,我们可以先看几个左值的例子。1.int a; 2.a = 1; // here, a is an lvalue 上述的a就是一个左值。临时变量可以做左值。同样函数的返回值也可以做左值。1.int x; 2.int& getRef ()