首页 > 解决方案 > C++ 向量如何不使用默认构造函数在内存空间中覆盖?

问题描述

这更像是一个理论问题而不是一个问题。

据我了解,std::vector 将在添加、删除或构造时动态调整内存大小/重新分配内存。

我有几个关于向量如何在最低级别工作的问题,使用下面的代码示例

  1. 是什么阻止了以下示例覆盖的内存空间string1

  2. 向量是否以与数组相同的方式连续?

  3. 如果一个向量需要一个可用的总内存,但它不是连续的,它是否会对内存空间进行碎片整理?

#include <vector>

using namespace std;

int main(){
    string string1 = "Some really large string";  

    /* A bunch of other random declarations take place 
    ...
    */

    vector<int> vector1;

    for(int i = 0; i < 10; i++)
    {
       vector1.push_back(i);
    }
}

标签: c++memoryvectortheory

解决方案


这些答案如何?

  1. 操作系统会(或任何处理您的内存分配的人)。通常向量和字符串的默认分配器调用操作系统在堆上分配内存。(非常小的字符串可能会与“小字符串优化,< ~16byte 字符串一起进入堆栈)。操作系统确保这些不会发生冲突。

  2. 是的,标准保证向量的连续内存。

  3. 不,它将请求它需要的大小块,并且操作系统(或任何分配器)将提供一个或失败。碎片整理是一项操作系统任务。

编辑:@parktomatomi 说的是正确的。std::vector<T>首先为 8 个元素分配足够的内存,然后在第 9 个元素中,他们将重新请求 16 个元素,复制所有内容并释放 8 个元素块。在 32 个元素处再次相同,等等。边界取决于实现,但它是一些东西像那样。您可以使用std::vector.reserve()来避免重新分配和复制过程。如果您有完美的信息,通常才值得,否则只需将其留给加倍算法通常就可以了。

std::array<T, N>与原始类型(int、double 等)一样,是固定大小和堆栈分配的。所以它的大小受到堆栈的限制。

Stack 也不会破坏(显然),因为它在每个变量声明中“将堆栈指针向下移动到新空间”。

现代桌面/服务器机器上的典型堆栈大小在 linux/OSX 上为 8MB,在 Windows 上为 1MB。这些都可以调整。堆大小(向量所在的位置)仅受机器中的物理内存(如果您不介意交换到磁盘,实际上是虚拟内存)的限制。所以通常是几个 GB。

这不是一篇关于这个主题的坏文章。https://www.tutorialspoint.com/cplusplus/cpp_dynamic_memory.htm

但请注意,它谈了很多关于new和的内容delete。99% 的时间你不应该使用这些。它们将在构造函数和析构函数的实现中“自动”发生std::vector(以及更多的地方)。


推荐阅读