我想我理解堆栈是如何工作的,当变量被移动时会发生什么,但是我找不到这个问题的答案。让我解释一下:将变量移动到外部作用域时堆栈会发生什么变化?
当一个新的作用域被输入/创建时,会在堆栈顶部获取一定量的内存。堆栈指针指向这个内存。它表示堆栈的当前大小。当范围被留下时,通过使堆栈指针返回到前一个位置来释放内存。
在C++ 11中移动语义或更高版本将一些数据的所有权从一个变量移动到另一个变量。这避免了复制数据,因为保存数据的内存保持不变。移动之后,移动到的变量指向数据在内存中的位置,移动的变量基本上变成空指针。在这里,我可能会犯第一个错误,将移动语义与指针过于紧密地联系起来。我是吗?
实际问题: 变量在内部作用域中创建,然后移动到外部作用域中的变量。然后内部范围退出。堆栈会发生什么?
鉴于上述情况,堆栈指针应该返回到它的前一个位置并释放内部作用域内存。但是它不能这样做,因为内部范围的内存仍然有效,因为它现在附加到外部范围变量。在外部(可能是全局的)范围和以前的内部范围内存之间可能存在大量的内存阻塞/浪费。一旦外部示波器退出,该内存便再次可用。在此之前,堆栈大小会膨胀。这是真的?这可以避免吗?编译器是否阻止了这一点?
“移动语义”并不意味着对象被物理移动到另一个位置。它只意味着由一个对象管理的状态(例如,在堆上分配的一块内存,对象持有一个指针)被以对象的类指定的方式交给另一个对象,这通常比对象的类更便宜制作该州的完整副本。这不会以任何方式影响如何分配或释放这些对象占用的内存,无论是堆栈还是其他内存。 –
这就是我的观点。移动后占用的内存保持不变,但是为了使堆栈正常工作,当范围离开时,范围内的所有内存应该被释放。也许我没有解释清楚。 – bjoern
移动语义仅适用于您有指向堆的指针的类(只要您应该注意)。你可以安全地浅拷贝你的课,因为你知道你对堆数据的所有权是你自己的,你以前的所有权是“移动”给你的。所以当你移动时,你关心的内存永远不会在堆栈中。您仍然复制您的堆栈对象(带有指向堆内存的类项),但与堆中所有数据的深层副本相比,这是小而可接受的。 – Troyseph