std::vector<int> get_vector()
{
std::vector<int> v = {1, 2, 3, 4, 5};
return v; // 依赖编译器进行返回值优化,消除多余的拷贝
}
虽然看起来像是在返回一个局部变量(通常会引发拷贝或者移动)
实际上大多数现代C++编译器都会对这种情况进行优化,直接在返回的位置上构造这个vector,避免了不必要的拷贝。
std::vector<int> get_vector()
{
std::vector<int> v = {1, 2, 3, 4, 5};
return std::move(v); // std::move 会将 v 标记为可移动,这样返回时就会调用移动构造函数,而不是拷贝构造函数
}
通过调用std::move,会导致v成为右值,进而触发vector的移动构造而非拷贝构造,避免了不必要的内存拷贝。
拷贝构造函数是用另一个同类型的对象来初始化新创建的对象。拷贝构造函数通常会创建一个新的对象,并从现有对象复制所有数据到新对象。
移动构造函数:移动构造函数是用于把资源(例如动态分配的内存)从一个对象转移到另一个对象,原对象将不再拥有这些资源。在执行移动构造函数后,原对象通常会处在一个有效但未定义的状态。
共同点:都用于初始化一个类类型的对象
拷贝构造函数会创建一个原对象的副本
移动构造函数只是将原对象的资源转移给新对象,而不是复制它们
拷贝构造函数用于对现有对象进行复制操作,移动构造函数通常用于优化这种复制操作
通过“窃取”临时对象(例如函数返回的临时对象)的资源,减少不必要的临时对象的创建和销毁
在处理动态内存分配的大对象时,使用移动构造函数通常比使用拷贝构造函数更有效
因为移动构造函数只是转移已分配的内存,而不需要分配新的内存。
对于现代C++,返回局部对象并不会引发性能问题,编译器通常会采取RVO/NRVO(返回值优化/命名返回值优化)
来避免多余的拷贝,对于C++11及之后的版本,利用移动语义同样可以获得高效的返回。