1、浅拷贝和深拷贝(和引用拷贝)
浅拷贝&深拷贝&引用拷贝?浅拷贝就是把表面的数据都拷贝一遍,但是指针指向的地址不会被拷贝。深拷贝就是所有的全部拷贝一遍。引用拷贝就是换个名字,指向的地址还是和原来一样。
2、左值和右值(和右值引用)
左值就是有具体函数名称的,表达式结束后依旧持久存在的对象;右值就是为了对某一个参数赋值而产生的临时性存在的数值。临时性存在,它的生命周期仅存在于对应表达式运行周期中。
之所以取名左值右值,是因为在等式左边的值往往是持久存在的左值类型,在等式右边的表达式值往往是临时对象。
右值临时存储在哪?
右值临时存储的位置并没有一个准确的定义。这取决于该右值本身的大小和CPU的优化策略:如果该右值是小型、简单的值(比如说简单数据类型),这是编译器优先选择的,那么它将会存储在CPU寄存器内;如果该右值更加简单,比如说只是一个常量,那么会直接变成CPU指令的一部分;如果该右值大型且复杂,或者说当前计算机寄存器剩余空间不足,那么它将被储存在栈内存中。
为什么要关心右值?
当有指向动态分配内存的属性时,会造成多个对象共用这块动态分配内存,从而可能导致冲突。一个可行的办法是:每次做浅拷贝后,必须保证原始对象不再访问这块内存(即转移所有权给新对象),这样就保证这块内存永远只被一个对象使用。
那有什么对象在被拷贝后可以保证不再访问这块内存呢?临时对象。所以我们发现,为了实现Copy这个功能,既用左值深拷贝实现(复制),也可以用右值更高效的资源转移实现(剪切)。(左值深拷贝在复制内容的同时还要分配内存;右值资源转移不会再重新分配内存,只是拷贝了指针和元数据,转移了对应资源的所有权。)
右值都有什么?
字面量(不包含字符字面量,它属于静态存储区)、临时的表达式值、临时的函数返还值都是。
//左值引用形参=>匹配左值
void Vector::Copy(Vector& v){this->num = v.num;this->a = new int[num];for(int i=0;i<num;++i){a[i]=v.a[i];}
}//右值引用形参=>匹配右值
void Vector::Copy(Vector&& temp){this->num = temp.num;this->a = temp.a;
}
左值引用和右值引用
C++11为了匹配左值右值,又引入了新的类型,右值引用&&,作用于对右值的匹配;左值引用,作用于左值的匹配。
注意:右值引用因为有一个变量名,所以其实也是左值。
//左值引用形参=>匹配左值
void Vector::Copy(Vector& v){this->num = v.num;this->a = new int[num];for(int i=0;i<num;++i){a[i]=v.a[i];}
}//右值引用形参=>匹配右值
void Vector::Copy(Vector&& temp){this->num = temp.num;this->a = temp.a;
}
左值可以用move()函数转化为右值使用
void func(){Vector result;//...DoSomething with resultif(xxx){ans = std::move(result);} //调用的是移动赋值构造函数return;
}
3、C++11对于左值右值的全新定义
更全面的定义出现了:左值(lvalue),右值(prvalue),将亡值(xvalue)
左值:有合法身份的