【发布时间】:2010-10-22 12:44:31
【问题描述】:
我在我的代码中痴迷地使用向量、列表、字符串和 wstrings。是否有任何涉及的 catch 22 让我对不时使用数组、chars 和 wchars 更感兴趣?
基本上,如果在支持标准模板库的环境中工作,是否有任何情况下使用原始类型实际上更好?
【问题讨论】:
标签: c++ arrays list vector std
我在我的代码中痴迷地使用向量、列表、字符串和 wstrings。是否有任何涉及的 catch 22 让我对不时使用数组、chars 和 wchars 更感兴趣?
基本上,如果在支持标准模板库的环境中工作,是否有任何情况下使用原始类型实际上更好?
【问题讨论】:
标签: c++ arrays list vector std
对于 99% 的时间和 99% 的标准库实现,您会发现 std::vectors 足够快,并且您从使用它们中获得的便利性和安全性将超过任何小的性能成本。
对于那些真正需要裸机代码的极少数情况,您可以将向量视为 C 样式数组:
vector <int> v( 100 );
int * p = &v[0];
p[3] = 42;
C++ 标准保证向量是连续分配的,所以这保证有效。
关于字符串,便利因素几乎是压倒性的,性能问题往往会消失。如果你回到 C 风格的字符串,你也会回到使用像 strlen() 这样的函数,这些函数本身就非常低效。
对于列表,在使用它们之前,您应该三思而后行,无论是您自己的实现还是标准。使用向量/数组可以更好地解决绝大多数计算问题。列表在文献中如此频繁出现的原因在很大程度上是因为它们是教科书和培训课程作者用来一次性解释指针和动态分配的一种方便的数据结构。我作为前培训课程作家在这里发言。
【讨论】:
我相信默认的内存分配技术是向量的缓冲区,而字符串是每次当前分配的内存用完时分配双倍内存的技术。这可能很浪费。您当然可以提供自定义分配器...
要考虑的另一件事是堆栈与堆。静态大小的数组和字符串可以放在堆栈上,或者至少编译器会为您处理内存管理。如果较新的编译器提供相关的 C99/C++0x 功能,它们也会为您处理动态大小的数组。向量和字符串将始终使用堆,如果您有非常严格的约束,这可能会引入性能问题。
根据经验,使用已有的内容,除非它的速度/内存开销会损害您的项目...您可能会发现,对于 99% 的内容,STL 提供的类可以节省您的时间和精力,几乎没有影响您的应用程序性能。 (即“避免过早优化”)
【讨论】:
我参与过几个项目,其中字符串的内存开销已经成为问题。
提前考虑您的应用程序需要如何扩展是值得的。如果您需要存储无限数量的字符串,使用const char*s 到全局托管的字符串表可以为您节省大量内存。
但一般来说,除非有很好的理由,否则绝对要使用 STL 类型。
【讨论】:
我会坚持使用 STL 类(向量、字符串等)。它们更安全、更易于使用、更高效,内存泄漏的可能性更小,而且,AFAIK,它们至少在调试时(Visual C++)对边界进行了一些额外的运行时检查。
然后,测量性能。如果您确定瓶颈在 STL 类上,则转到 C 风格的字符串和数组用法。
根据我的经验,向量或字符串使用出现瓶颈的可能性非常低。
【讨论】:
你偶尔会遇到这样的场景,你可以通过自己做一些事情来获得更好的性能或内存使用(例如,std::string 通常有大约 24 个字节的开销,12 个字节用于 std::string 本身的指针, 以及在其动态分配的部分上的标题块)。
我从事的项目是从 std::string 转换为 const char* 节省了显着的内存(10 MB)。我不相信这些项目是你所说的典型。
哦,使用 STL 会影响您的编译时间,而且在某些时候这可能是个问题。当您的项目导致将超过 GB 的目标文件传递给链接器时,您可能需要考虑其中有多少是模板膨胀。
【讨论】:
一个问题是访问元素时的开销。即使使用向量和字符串,当您通过索引访问元素时,您也需要首先检索缓冲区地址,然后添加偏移量(您无需手动执行此操作,但编译器会发出此类代码)。使用原始数组,您已经有了缓冲区地址。在某些情况下,这种额外的间接性可能会导致大量开销,并且在您想要提高性能时会受到分析。
【讨论】:
operator[],而是使用迭代器。他们经常将 char * 映射到底层字符数组中。
如果您不需要实时响应,请坚持使用您的方法。它们比字符更安全。
【讨论】: