这是一个关于堆栈内存和堆内存交互的问题,以及通过 std::array
从堆栈到堆的特殊情况。和 std::vector
类。
原则上std::array<T>
可以看作是指向第一个元素的指针,加上一些关于数组大小的编译时信息。是否有可能有 std::vector<T>
考虑到这一事实并尝试 move array
内容的构造函数进vector
只是通过复制指针。
一个用例是,它有一个返回 std::array<double, >
的函数。std::array<double, 20> fun(){...};
但后来决定将其分配给 std::vector
无需逐个复制元素。std::vector<double> v = fun(); // not working code
现在必须做
std::array<double, 20> tmp = fun();
std::vector<double> v(tmp.begin(), tmp.end());
这实际上做了一些多余的工作,如果可能的话,这些工作是不必要的
std::vector<double> v(std::move(tmp)); \\ not working code
.
std::vector
的内存布局和
std::array
是一样的,所以这不是和障碍。
我知道主要障碍可能是
std::array
元素在堆栈中,而 std::vector
元素在堆中 .很明显,即使为
std::vector
编写了 move 构造函数。堆栈中的内存仍将不可撤销地销毁。
所以我想这个问题也可以理解为:
有没有办法将内存从堆栈 move 到堆(无论这意味着什么),以及是否可以与 move 构造函数结合使用?
或者如果
std::vector
原则上可以有一个来自 std::array
的 move 构造函数?
MWE:
#include<array>
#include<vector>
std::array<double, 20> fun(){return {};} // don't change this function
int main(){
std::array<double, 20> arr = fun(); // ok
std::vector<double> v(arr.begin(), arr.end()); // ok, but copies and the allocation is duplicated
std::vector<double> v2 = fun(); // not working, but the idea is that the work is not duplicated
}
请您参考如下方法:
Is there a way to move memory from the stack to the heap (whatever that means) and if that can be combined with a move constructor?
我个人喜欢“无论这意味着什么”这一点。让我们暂时考虑一下。将某些东西从堆栈 move 到堆会突然意味着堆栈的那部分突然被标记为堆分配区域并受到定期破坏。
这样做的问题是堆栈是连续的,并且会被从堆栈中弹出的东西破坏。你不能只是说“嘿,把这个内存位留下来”——任何连续的堆栈分配和释放都需要“跳过”那部分。
为了显示:
| |
|----------------------|
| stack block 1 |
|----------------------|
| your vector |
|----------------------|
| stack block 2 |
|----------------------|
|- -|
如果您想展开这两个块,您需要首先将堆栈指针减少块 2 指针的大小,然后减少向量和块 1 的大小。这真的不是可能发生的事情。
因此,这里唯一可行的解决方案是复制到堆内存区域。然而,这些副本比很多人预期的要快得多。即使向量有几兆字节,我想内存 Controller 也可以交换一些页面,而不必物理发送与数据位相对应的电信号。
此外,向量的任何调整都需要导致重新分配。由于数组占用的内存正好与其需要的一样多,因此即使添加单个元素也会触发您试图避免的副本。