在 C++ 中,"移动版本" 是指使用了移动构造函数或移动赋值运算符的对象构造过程。这种过程可以显著减少资源的复制开销。
移动语义简介
移动语义允许将资源(如动态分配的内存)从一个对象转移到另一个对象,而不是复制这些资源。它通过以下方式实现:
- 移动构造函数:用于创建一个新对象,并将资源从一个已有对象(源对象)转移到新对象(目标对象)。
- 移动赋值运算符:用于将一个已有对象的资源转移到另一个已有对象,并清理源对象的资源。
移动操作的堆栈和堆变化
-
移动构造函数:
-
堆(Heap):
- 在移动构造函数中,源对象的资源(如动态内存)会被转移到新对象。这通常会涉及从堆中获取资源指针并将其设置到新对象中。源对象的资源指针会被设置为
nullptr
或其他默认值,以避免重复释放。 - 如果目标对象的堆内存已经分配,它可能需要调整大小以适应新资源。否则,目标对象会在堆上分配新的内存。
- 在移动构造函数中,源对象的资源(如动态内存)会被转移到新对象。这通常会涉及从堆中获取资源指针并将其设置到新对象中。源对象的资源指针会被设置为
-
栈(Stack):
- 移动构造函数的参数(即源对象)是栈上的临时对象。在构造过程中,这些参数的生命周期只在函数调用期间。源对象的资源会被转移到目标对象,源对象在构造函数执行后仍然存在于栈上,但其资源状态可能被修改。
-
示例:
std::vector<std::string> vec1; vec1.push_back("Hello"); // 使用 push_back 进行复制 std::vector<std::string> vec2 = std::move(vec1); // 使用移动构造函数
在这个例子中,
vec2
使用移动构造函数从vec1
迁移资源,vec1
变为空(或状态未定义)。
-
-
移动赋值运算符:
-
堆(Heap):
- 移动赋值运算符将资源从源对象转移到目标对象。如果目标对象已经持有资源,它可能会先释放旧资源,然后获取源对象的资源。源对象的资源会被转移(如设置为
nullptr
)以避免重复释放。
- 移动赋值运算符将资源从源对象转移到目标对象。如果目标对象已经持有资源,它可能会先释放旧资源,然后获取源对象的资源。源对象的资源会被转移(如设置为
-
栈(Stack):
- 源对象和目标对象在栈上作为函数参数传递。在赋值操作过程中,目标对象的状态会被修改,源对象的资源会被转移。
-
示例:
std::vector<std::string> vec1; vec1.push_back("Hello"); std::vector<std::string> vec2; vec2 = std::move(vec1); // 使用移动赋值运算符
在这个例子中,
vec2
接受了vec1
的资源,vec1
变为空。
-
总结
-
堆:在移动构造函数和移动赋值运算符中,堆内存的变化包括资源的转移或重新分配。移动操作通常避免了不必要的复制,减少了资源分配和释放的开销。
-
栈:移动操作的参数(源对象)通常是在栈上。移动构造函数和移动赋值运算符只涉及对源对象和目标对象的栈上状态的修改,不涉及实际资源的复制。
通过理解移动语义可以编写更高效的 C++ 代码,减少不必要的资源复制和提高程序的性能。
标签:对象,语义,运算符,vec1,移动,资源,构造函数 From: https://www.cnblogs.com/niumachen/p/18419295