【发布时间】:2010-10-19 12:25:21
【问题描述】:
我相信,在 C++ 中,处理重新分配的更好方法是使用 STL 向量,因为它保证了连续的存储位置。
我有几个问题要理解其中的区别:
谢谢,
【问题讨论】:
我相信,在 C++ 中,处理重新分配的更好方法是使用 STL 向量,因为它保证了连续的存储位置。
我有几个问题要理解其中的区别:
谢谢,
【问题讨论】:
只有vector,保证有连续内存。不是其他人。
realloc 是一个 C 内存管理函数。在 C++ 代码中不鼓励使用它。下面是 Stroustrup 告诉你原因:Why doesn't C++ have an equivalent to realloc()?
但是,realloc() 只能保证在 malloc()(和类似函数)分配的数组上工作,这些数组包含没有用户定义的复制构造函数的对象。另外,请记住,与天真的期望相反,realloc() 偶尔会复制其参数数组。
【讨论】:
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 的等价物是一个结构,它保存指向内存缓冲区的指针、使用的元素计数和保留的(缓冲区大小)以及处理根据需要获取更多内存和更新的函数集每个操作的索引。
【讨论】:
std::vector<T>(myVector).swap( myVector ); 将在我知道(非强制)的所有实现中将矢量缩小到适当的大小。
realloc 也保证了连续的内存,所以这不是不使用它的理由。
但是,我更喜欢在 C++ 中使用向量,因为它处于更高的抽象级别,因此它使代码更容易编写。
我认为在数组类型场景中使用 realloc(通过向量)的唯一可能原因是原始速度。它可能会更快。我强调“可能”这个词 - 衡量,不要猜测!
但是,您必须自己处理重新分配,这需要更多的工作。如果我可以交付它并更快地获得报酬,我宁愿让代码运行得更慢一些(当然,假设它仍然运行得足够快)。
【讨论】:
std::vector 的主要好处之一是,当它在内部从自然增长中重新分配自身时,它会选择比当前大小大 2 倍的大小(通常 - 但总是一个常数乘数)。这意味着 push_back 已经摊销了 O(1) 成本。
Realloc 可以让您更好地控制分配内存的方式,但强大的功能也带来了巨大的责任。如果你所做的一切相当于 push_back,并且每次添加元素时都重新分配,那么可能对数组的每次添加都进行 O(N) 操作。
【讨论】:
我猜它只是一个向量。
我还没有看到有人建议在 C++ 中使用 realloc。
【讨论】: