7

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

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

  1. 在任何情况下我需要更喜欢realloc而不是 vector ?
  2. 还有什么(除了 vector )相当于C++中的realloc吗?

谢谢,

4

5 回答 5

15

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

realloc是一个 C 内存管理函数。在 C++ 代码中不鼓励使用它。Stroustrup 告诉你原因:为什么 C++ 没有 realloc() 的等价物?

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

于 2009-04-15T04:49:40.253 回答
10

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++ 操作在新位置复制(或构造复制)所有对象,然后再删除旧元素。

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

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

于 2009-04-15T06:05:12.287 回答
8

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

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

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

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

于 2009-04-15T04:47:16.203 回答
5

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

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

于 2009-04-15T13:16:51.407 回答
1

我想这只是一个向量。

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

于 2009-04-15T05:23:25.710 回答