将变量移动到外部作用域时堆栈会发生什么变化?
What happens to the stack when moving a variable to an outer scope?
我想我了解堆栈的工作原理以及移动变量时会发生什么,但我找不到这个问题的答案。让我解释一下:
当新作用域为entered/created时,在栈顶获取一定量的内存。栈指针指向这块内存。它代表堆栈的当前大小。当范围离开时,通过将堆栈指针 return 指向其先前位置来释放内存。
在 C++11 或更高版本中移动语义,将某些数据的所有权从一个变量移动到另一个变量。这避免了复制数据,因为保存数据的内存保持不变。 move之后,moved-to变量指向数据在内存中的位置,moved-from变量基本上变成了空指针。在这里,我可能会犯第一个错误,将移动语义与指针联系得太紧密。我是吗?
实际问题:
变量在内部作用域中创建,然后移动到外部作用域中的变量。然后内部范围退出。堆栈发生了什么变化?
鉴于上述情况,堆栈指针应该 return 指向它之前的位置并释放内部作用域内存。但它不能这样做,因为来自内部范围的内存仍然有效,因为它现在附加到外部范围变量。外部(可能是全局)范围和以前的内部范围内存之间可能有很多内存 blocked/wasted。一旦外部范围退出,此内存将再次可用。在此之前,筹码量会膨胀。这是真的?这可以避免吗?编译器会阻止这种情况吗?
免责声明、外行术语、狡猾的类比和不可靠的 c++ 知识...
我想我理解你的困惑,
[stack frame a]
std::vector toPopulate;
[stack frame b]
std::vector toMove; // will be std::moved into `toPopulate` somehow
当堆栈范围离开 b
并返回到 a
时,move
如何阻止任何复制,因为您显然不能将内存留在堆栈帧中 b
...
答:不是! toMove
的堆栈数据被复制到 toPopulate
,std::vector
不将数组的内容存储在堆栈中,它仅将 address/pointer 存储到内存中的位置堆。
std::move
这里是在告诉vector
不要深拷贝自己(不要将堆数据拷贝到堆中的其他地方),只拷贝data
指针,相信我,这样做是安全的,安全是在编译时强制执行的。
所以 toPopulate
被构建,它的 dataCount 和 dataPointer 以及描述 std::vector 可能需要的任何其他东西都 written/copied 到堆内存中,但你的堆数据没有被触及,它也不会被堆栈中的多个 std::vectors
拥有,这确实很麻烦!
我想我了解堆栈的工作原理以及移动变量时会发生什么,但我找不到这个问题的答案。让我解释一下:
当新作用域为entered/created时,在栈顶获取一定量的内存。栈指针指向这块内存。它代表堆栈的当前大小。当范围离开时,通过将堆栈指针 return 指向其先前位置来释放内存。
在 C++11 或更高版本中移动语义,将某些数据的所有权从一个变量移动到另一个变量。这避免了复制数据,因为保存数据的内存保持不变。 move之后,moved-to变量指向数据在内存中的位置,moved-from变量基本上变成了空指针。在这里,我可能会犯第一个错误,将移动语义与指针联系得太紧密。我是吗?
实际问题: 变量在内部作用域中创建,然后移动到外部作用域中的变量。然后内部范围退出。堆栈发生了什么变化?
鉴于上述情况,堆栈指针应该 return 指向它之前的位置并释放内部作用域内存。但它不能这样做,因为来自内部范围的内存仍然有效,因为它现在附加到外部范围变量。外部(可能是全局)范围和以前的内部范围内存之间可能有很多内存 blocked/wasted。一旦外部范围退出,此内存将再次可用。在此之前,筹码量会膨胀。这是真的?这可以避免吗?编译器会阻止这种情况吗?
免责声明、外行术语、狡猾的类比和不可靠的 c++ 知识...
我想我理解你的困惑,
[stack frame a]
std::vector toPopulate;
[stack frame b]
std::vector toMove; // will be std::moved into `toPopulate` somehow
当堆栈范围离开 b
并返回到 a
时,move
如何阻止任何复制,因为您显然不能将内存留在堆栈帧中 b
...
答:不是! toMove
的堆栈数据被复制到 toPopulate
,std::vector
不将数组的内容存储在堆栈中,它仅将 address/pointer 存储到内存中的位置堆。
std::move
这里是在告诉vector
不要深拷贝自己(不要将堆数据拷贝到堆中的其他地方),只拷贝data
指针,相信我,这样做是安全的,安全是在编译时强制执行的。
所以 toPopulate
被构建,它的 dataCount 和 dataPointer 以及描述 std::vector 可能需要的任何其他东西都 written/copied 到堆内存中,但你的堆数据没有被触及,它也不会被堆栈中的多个 std::vectors
拥有,这确实很麻烦!