将变量移动到外部作用域时,堆栈会发生什么?

时间:2017-10-08 20:54:42

标签: c++11 memory-management stack move-semantics

我想我理解堆栈是如何工作的以及变量移动时会发生什么,但我找不到这个问题的答案。让我解释一下:

当输入/创建新范围时,在堆栈顶部获取一定量的内存。堆栈指针指向此内存。它表示堆栈的当前大小。保留范围时,通过使堆栈指针返回到其先前位置来释放内存。

在C ++ 11或更高版本中移动语义会将某些数据的所有权从一个变量移动到另一个变量。这避免了复制数据,因为保存数据的内存保持不变。移动后,move-to变量指向数据在内存中的位置,move-from变量基本上变为空指针。在这里,我可能会犯第一个错误,将移动语义与指针过于紧密联系起来。我呢?

实际问题: 变量在内部作用域中创建,然后移动到外部作用域中的变量。然后内部范围退出。堆栈会发生什么?

鉴于上述情况,堆栈指针应该返回到它的先前位置并释放内部范围内存。但它不能这样做,因为内部作用域的内存仍然有效,因为它现在附加到外部作用域变量。在外部(可能是全局)范围和以前内部范围内存之间可能存在大量内存被阻塞/浪费。一旦外部示波器退出,该存储器将再次可用。在此之前,堆栈大小是膨胀的。这是真的?这可以避免吗?编译器会阻止这个吗?

1 个答案:

答案 0 :(得分:0)

免责声明,外行人的术语,狡猾的类比和不稳定的c ++知识......

我想我理解你的困惑,

[stack frame a]
std::vector toPopulate;
    [stack frame b]
    std::vector toMove; // will be std::moved into `toPopulate` somehow

当堆栈范围离开b并返回a时,move如何阻止任何复制,因为您显然无法将内存留在堆栈帧{{1} } ...

答案:它没有! b的堆栈数据被复制到toMovetoPopulate没有将其内容存储在堆栈中,它只存储一个地址/指针,指向内存所在的位置堆。

std::vector在这里做的是告诉std::move不要自己深层复制(不要将堆数据复制到堆中的另一个地方),只需复制vector指针,相信我,这样做是安全的,在编译时强制执行。

所以构造data,其dataCount和dataPointer以及描述std :: vector所需的任何其他东西都被写入/复制到堆内存中但​​你的堆数据没有被触及,也没有它曾经被堆栈中的多个toPopulate所拥有,这确实很麻烦!