- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
假设我必须迭代一个可能非常大的数字 vector ,并将偶数和奇数元素复制到新的、单独的 vector 中。 (源 vector 的偶数与奇数的比例可以是任意的;它可以是全偶数、全奇数或介于两者之间。)
为简单起见,push_back
通常用于此类事情:
for (std::size_t Index; Index < Source.size(); Index++)
{
if (Source[Index] % 2) Odds.push_back(Source[Index]);
else Evens.push_back(Source[Index]);
}
但是,我担心如果将其用作排序算法等性能至关重要的实现的一部分,这将是低效且有害的。例如,快速排序涉及像这样分离元素。
您可以使用 reserve()
预先分配内存,因此只需要一次分配,但随后您必须遍历整个源 vector 两次 - 一次计算需要多少元素进行整理,并再次进行实际复制。
当然,您可以分配与源 vector 大小相同的空间量,因为两个新 vector 都不需要容纳超过该大小的空间,但这似乎有些浪费。
有没有我缺少的更好的方法? push_back()
通常可以信任为程序员管理此类事情,还是会成为敏感算法的负担?
最佳答案
我将回答我认为您真正想问的问题,即“是否应该在繁重算法的内部循环中避免使用 push_back()
?”而不是其他人似乎已经读到你的帖子,这是“如果我在对大 vector 进行不相关排序之前调用 push_back 有关系吗?”此外,我将根据我的经验来回答,而不是花时间追查引用和同行评审的文章。
您的示例基本上做了两件事,这些事情加起来会增加总 CPU 成本:它读取输入 vector 中的元素并对其进行操作,然后它必须将元素插入输出 vector 。您担心插入元素的成本,因为:
malloc()
is just slow,即使学究们假装 new
是不同的)因此,您的直觉是正确的:始终尽可能为您的 vector 预留空间,不是因为 push_back 很慢,而是因为它会触发一个很慢的重新分配。此外,如果您查看 shrink_to_fit
的实现,您会发现它还会进行复制重新分配,暂时使内存成本翻倍并导致进一步碎片化。
这里的问题是您并不总是确切知道输出 vector 需要多少空间;通常的 react 是使用启发式分配器,也可能使用自定义分配器。默认情况下,为每个输出 vector 保留 n/2+k 的输入大小,其中 k 是一些安全边际。这样一来,您通常就会有足够的空间用于输出,只要您的输入合理平衡,并且 push_back 可以在极少数情况下重新分配。如果你发现 push_back 的指数行为浪费了太多内存(导致你保留 2n 个元素,而实际上你只需要 n+2 ),你可以给它一个自定义分配器,以更小的线性 block 扩展 vector 大小——当然如果 vector 真的不平衡并且你最终会做很多调整大小,那会慢得多。
如果不提前遍历输入元素,就无法始终保留准确的空间量;但是如果您知道平衡通常是什么样子,您可以使用启发式方法对其进行很好的猜测,以便在多次迭代中获得统计性能增益。
关于c++ - 聪明地处理 vector 内存分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6804568/
Closed. This question is opinion-based。它当前不接受答案。
我知道如何创建和编写我自己的安装程序,但我需要在某些时候被重定向。这一点我肯定也会启发其他人。 我创建了一个安装项目。一切都完成了。 EXE 中的安装文件除外。 我知道有两种不同的方法: 在 EXE
重复 What is a PHP Framework?and many more 到目前为止,我一直在使用 PHP 进行小的调整,主要是使用 WordPress。什么是 PHP 框架?为什么我需要它们
我刚刚发现 String#split 有以下奇怪的行为: "a\tb c\nd".split => ["a", "b", "c", "d"] "a\tb c\nd".split(' ') => ["a
我是一名优秀的程序员,十分优秀!