C++:以数组的方式使用std::vectors是否安全?

10

我需要一个固定大小的元素数组,并调用需要了解它们在内存中的放置方式的函数,特别是:

  • 例如需要知道顶点在哪里、彼此之间的距离等的函数,如glVertexPointer。在我的情况下,顶点将是要存储的元素的成员。

  • 为了获得该数组中元素的索引,我更倾向于避免在我的元素内部设置一个index字段,而是通过指针算术来处理(即:Element *x 的索引将是x- &array[0])--顺便说一句,对我来说这听起来有些麻烦:这是好的做法还是应该做其他事情?


对于这个问题使用std::vector安全吗?

某些东西让我认为std::array更合适,但有以下方面需要考虑:

  • 我结构体的构造函数和析构函数很少会被调用:我不介意这种开销。

  • 我将设置std::vector的容量为我需要的大小(与使用std::array的大小相同),因此不会有由于偶发重分配而产生的任何开销。

  • 我不介意std::vector内部结构的一些空间开销。

  • 我可以使用调整向量大小的能力(或更好地说:在设置期间选择大小),我认为这是没有办法使用std::array实现的,因为其大小是一个模板参数(太糟糕了:即使使用旧的类似C的数组也可以在堆上动态分配它)。


如果std::vector适用于我的目的,我想详细了解与std::array(或纯C数组)相比是否会有一些运行时开销:

我知道,当我增加容器的大小时,它会调用每个元素的默认构造函数(但如果我的数据有一个空的默认构造函数,这应该不会花费任何时间),析构函数也是一样。还有其他需要注意的吗?

在调用glVertexPointer之后最好不要调整向量的大小,除此之外就没问题了。 - Ben Voigt
可能是将std::vector转换为数组的重复问题。 - mmmmmm
6个回答

5

向量保证所有元素都在连续的内存中,因此在您的情况下使用是安全的。与C风格数组相比,可能会有一些性能损失,例如由于向量实现所进行的索引验证。 在大多数情况下,性能取决于其他因素,因此在实际性能测量显示这是一个真正的问题之前,我不会担心这个问题。

正如其他人指出的那样,如果您正在使用指向元素(或迭代器)来访问它,则确保在使用存储在其中的数据时不要重新分配向量。


标准实际上并不要求元素在连续的内存中存储。 - moinudin
8
C++03标准规定了这一点。尽管C++98标准未规定,但无论如何都是如此,详情请见http://herbsutter.com/2008/04/07/cringe-not-vectors-are-guaranteed-to-be-contiguous/。 - villintehaspam
1
@vil 感谢您纠正我,我之前不知道这个变化! - moinudin
在大多数情况下,性能是由其他因素决定的。 - nimcap
@Martin York:我主要是指Visual Studio 2005中的已检查迭代器(http://msdn.microsoft.com/en-us/library/aa985965.aspx),我们不得不禁用它们以获得某些代码的最佳性能(但在调试构建中当然保持启用)。 - villintehaspam
显示剩余4条评论

2

将std::vector中的数据视为数组进行处理,并使用&v[0]获取指向其开头的指针是可行的。显然,如果进行任何可能重新分配数据的操作,则您的指针可能会失效。


0

没错,你可以在OpenGL中将它用作数组 :) 例如:

glBufferData( GL_ARRAY_BUFFER_ARB, dataVec.size() * sizeof( dataVec[0] ), &dataVec[0], GL_STATIC_DRAW_ARB );

其中 dataVec 是 std::Vector


0

它甚至比在堆栈上有一个数组更安全:你的堆栈有多大?你的数组可能会变得多大(固定大小,但大小可以在以后的版本中增加)?


0
如果你真的想要一个std::array,你可以使用boost::array。它就像一个普通的数组,但支持迭代器,并且你可以轻松地将其与STL算法一起使用。

0
在多线程环境和动态内存分配中工作可能会导致问题,因为向量通常是连续的内存块,并且指针可能不一定连续!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接