我是 C++ 新手。我正在阅读 Michael Dawson 的《通过游戏编程开始 C++》。不过,总的来说,我对编程并不陌生。我刚刚完成了关于向量的一章,所以我有一个关于它们在现实世界中的使用的问题(我是一名计算机科学专业的学生,所以我还没有太多的现实世界经验)。
作者在每章末尾都有一个 Q/A,其中一个是:
问:什么时候应该使用向量而不是数组?
答:几乎总是如此。向量高效且灵活。它们确实需要比数组多一点的内存,但这种权衡几乎总是值得的。
你们有什么感想?我记得在一本 Java 书中学习过向量,但我们在我的 Intro to Comp 中根本没有涉及它们。科学。课,也不是我大学的数据结构课。我也从未见过它们在任何编程作业(Java 和 C)中使用。这让我觉得它们并没有被经常使用,尽管我知道学校代码和现实世界的代码可能非常不同。
我不需要被告知这两种数据结构之间的差异;我非常了解他们。我想知道的是作者是否在他的问答中给出了好的建议,或者他是否只是想避免初学者程序员因管理固定大小数据结构的复杂性而毁掉自己。另外,无论您如何看待作者的建议,您认为如何?see在现实世界中更频繁?
答:几乎总是[使用向量而不是数组]。向量高效且灵活。它们确实需要比数组多一点的内存,但这种权衡几乎总是值得的。
这过于简单化了。使用数组相当常见,并且在以下情况下很有吸引力:
-
这些元素是在编译时指定的,例如const char project[] = "Super Server";
, const Colours colours[] = { Green, Yellow }
;
- with C++11 it will be equally concise to initialise
std::vector
s with values
元素的数量本质上是固定的,例如const char* const bool_to_str[] = { "false", "true" };
, Piece chess_board[8][8];
-
首次使用性能至关重要:使用常量数组,编译器通常可以将完全预初始化对象的内存快照写入可执行映像,然后将其直接页错误到准备使用的位置,因此通常要快得多运行时堆分配(new[]
) 然后是对象的序列化构造
编译器生成的表const
数据始终可以被多个线程安全地读取,而在运行时构造的数据必须在非函数本地构造函数触发其他代码之前完成构造static
变量尝试使用该数据:您最终需要某种方式的单例(可能是线程安全的,这会更慢)
在 C++03 中,vector
使用初始大小创建的 s 将构造一个原型元素对象,然后复制构造每个数据成员。这意味着,即使对于故意将构造保留为无操作的类型,复制数据元素仍然存在成本 - 复制它们在内存中留下的任何垃圾值。显然,未初始化元素的数组速度更快。
C++ 的强大功能之一是您通常可以编写一个class
(or struct
),它精确地模拟了特定协议所需的内存布局,然后将类指针指向您需要使用的内存,以方便地解释或分配值。无论好坏,许多此类协议通常嵌入小型固定大小的数组。
有一个几十年前的黑客方法,将一个包含 1 个元素的数组(如果编译器允许它作为扩展,甚至是 0 个元素)放在结构/类的末尾,将指向结构类型的指针指向某个更大的数据区域,并访问基于内存可用性和内容的先验知识,数组元素离开结构的末尾(如果在写入之前读取) - 请参阅零元素数组需要什么?
包含数组的类/结构仍然可以是 POD 类型
数组有助于从多个进程访问共享内存(默认情况下vector
指向实际动态分配数据的内部指针不会位于共享内存中,也不会跨进程有意义,并且众所周知,强制 C++03 很困难vector
即使指定自定义分配器模板参数,也可以像这样使用共享内存)。
嵌入数组可以本地化内存访问需求,提高缓存命中率,从而提高性能
也就是说,如果使用vector
(在代码简洁性、可读性或性能方面)那么你最好这样做:他们已经size()
,通过检查随机访问at()
、迭代器、调整大小(随着应用程序“成熟”,这通常变得必要)等。从vector
如果需要,可以更安全/更轻松地应用标准算法(x.end()
比x + sizeof x / sizeof x[0]
任何一天)。
更新:C++11 引入了std::array<>
,这避免了一些成本vector
s - 内部使用固定大小的数组来避免额外的堆分配/释放 - 同时提供一些好处和 API 功能:http://en.cppreference.com/w/cpp/container/array.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)