【问题标题】:Is STL vector a better version of realloc?STL 向量是 realloc 的更好版本吗?
【发布时间】:2010-10-19 12:25:21
【问题描述】:

我相信,在 C++ 中,处理重新分配的更好方法是使用 STL 向量,因为它保证了连续的存储位置。

我有几个问题要理解其中的区别:

  1. 在任何情况下我需要更喜欢 realloc 而不是矢量?
  2. 在 C++ 中,还有什么(除了向量)等价于 realloc 吗?

谢谢,

【问题讨论】:

    标签: c++ stl vector realloc


    【解决方案1】:

    只有vector,保证有连续内存。不是其他人。

    realloc 是一个 C 内存管理函数。在 C++ 代码中不鼓励使用它。下面是 Stroustrup 告诉你原因:Why doesn't C++ have an equivalent to realloc()?

    但是,realloc() 只能保证在 malloc()(和类似函数)分配的数组上工作,这些数组包含没有用户定义的复制构造函数的对象。另外,请记住,与天真的期望相反,realloc() 偶尔会复制其参数数组。

    【讨论】:

    • realloc 不能用于除 POD 类型之外的任何东西,因为它不知道构造函数/析构函数。
    • vector 也比 malloc 的内存具有优势,因为它们会在超出范围时被删除,从而减少抛出异常、忘记释放内存等时的内存泄漏。
    • @GiovanniFunchal 修复了链接。
    【解决方案2】:

    C 函数集(malloc、calloc、realloc、free)是原始内存操作。他们将在内存中创建/修改/释放给定的缓冲区,但内存将没有类型,也不会调用构造函数。

    C++ 没有 realloc 的等价物,只有通过使用 new/new[]delete/delete 的 malloc/free 的类型安全等价物[]。 C++ 版本将从系统获取内存通过调用适当的构造函数对其进行初始化。使用 delete 将调用对象的析构函数,然后释放内存。 C 和 C++ 版本不兼容,如果您使用 malloc 获取内存(即使您在收到的内存上调用就地构造函数),您无法使用 delete/delete[]释放它> 因为它是未定义的行为。

    在 C++ 中使用 realloc 可能不安全,因为它会按位将对象从一个内存区域复制到下一个内存区域。有时您的对象无法正确处理内存移动(假设您的对象既有属性又有对它的引用,在按位移动它之后,引用将指向旧位置而不是真实属性)。在 vector 内部,每当内存需要增长时,都会使用 new[] 获取新的内存,然后使用在删除旧元素之前进行适当的 C++ 操作。

    每当 vector 的大小(保留大小,未使用大小)增长时,它将创建一个完整的新内存区域并移动所有对象。另一方面,realloc 只会将内存块移动到另一个位置,如果在指针之后没有足够的连续空间来 grow 它。 向量不会减小大小。绝不。当您清除元素时,保留的内存仍然保留。

    最后,vector 中的抽象级别比 realloc 中的更高,即使对于 POD 类型(使用类似 C 的结构可以安全地移动)也是如此。 vector 的等价物是一个结构,它保存指向内存缓冲区的指针、使用的元素计数和保留的(缓冲区大小)以及处理根据需要获取更多内存和更新的函数集每个操作的索引。

    【讨论】:

    • 向量不会减小大小,除非调用 v.shrink_to_fit(),这是 C++11 中的新功能。请注意,实现可以选择忽略调用。
    • @MaHuJa:std::vector<T>(myVector).swap( myVector ); 将在我知道(非强制)的所有实现中将矢量缩小到适当的大小。
    【解决方案3】:

    realloc 也保证了连续的内存,所以这不是不使用它的理由。

    但是,我更喜欢在 C++ 中使用向量,因为它处于更高的抽象级别,因此它使代码更容易编写。

    我认为在数组类型场景中使用 realloc(通过向量)的唯一可能原因是原始速度。它可能会更快。我强调“可能”这个词 - 衡量,不要猜测!

    但是,您必须自己处理重新分配,这需要更多的工作。如果我可以交付它并更快地获得报酬,我宁愿让代码运行得更慢一些(当然,假设它仍然运行得足够快)。

    【讨论】:

      【解决方案4】:

      std::vector 的主要好处之一是,当它在内部从自然增长中重新分配自身时,它会选择比当前大小大 2 倍的大小(通常 - 但总是一个常数乘数)。这意味着 push_back 已经摊销了 O(1) 成本。

      Realloc 可以让您更好地控制分配内存的方式,但强大的功能也带​​来了巨大的责任。如果你所做的一切相当于 push_back,并且每次添加元素时都重新分配,那么可能对数组的每次添加都进行 O(N) 操作。

      【讨论】:

        【解决方案5】:

        我猜它只是一个向量。

        我还没有看到有人建议在 C++ 中使用 realloc。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-11-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-28
          • 2018-01-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多