在C ++中的vector存储

我希望存储一个d维点的大向量(d fixed和small:<10)。

如果我将一个Point定义为vector<int> ,我认为一个vector<Point>将在每个位置存储一个指向Point的指针。

但是,如果将Point定义为像std::tuple<int,int,...,int>std::array<int, d>这样的固定大小的对象,程序会将所有点存储在连续的内存中还是将间接的额外水平仍然存在?

如果答案是数组避免了额外的间接寻址,那么在扫描vector<Point>会不会影响性能(caching利用本地化)?

如果将Point定义为具有连续的数据存储(例如struct Point { int a; int b; int c; }或使用std::array ),则std::vector<Point>将把Point存储在连续的内存位置,所以你的内存布局将是:

 p0.a, p0.b, p0.c, p1.a, p1.b, p1.c, ..., p(N-1).a, p(N-1).b, p(N-1).c 

另一方面,如果将Point定义为vector<int> ,则vector<Point>具有vector<vector<int>>的布局,因为vector存储指向dynamic分配的内存的指针 ,所以它不是连续的。 所以你有 Point的连续性,但不是整个结构。

第一个解决scheme比第二个解决scheme更有效率(因为现代CPU喜欢访问连续的内存位置)。

vector将存储你的types包含在连续的内存中。 所以是的,如果这是一个arraytuple ,或者甚至更好的自定义types,它将避免间接。

性能方面,一如既往,你必须测量它。 不要揣测。 至less就扫描而言。

但是,当你首先创build这些点时,肯定会有巨大的性能提升,因为你将避免为存储点的每个vector分配不必要的内存。 内存分配在C ++中通常非常昂贵。

对于d (<10)的值,将Point定义为vector<int>将使std::vector<Point>内存使用量增加近一倍,并且几乎没有优势。

由于维度是固定的,我build议你去使用维度作为模板参数的模板。 像这样的东西:

 template <typename R, std::size_t N> class ndpoint { public: using elem_t= typename std::enable_if<std::is_arithmetic<R>::value, R>::type; static constexpr std::size_t DIM=N; ndpoint() = default; // eg for copying from a tuple template <typename... coordt> ndpoint(coordt... x) : elems_ {static_cast<R>(x)...} { } ndpoint(const ndpoint& other) : elems_() { *this=other; } template <typename PointType> ndpoint(const PointType& other) : elems_() { *this = other; } ndpoint& operator=(const ndpoint& other) { for(size_t i=0; i<N; i++) { this->elems_[i]=other.elems_[i]; } return *this; } // this will allow you to assign from any source which defines the // [](size_t i) operator template <typename PointT> ndpoint& operator=(const PointT& other) { for(size_t i=0; i<N; i++) { this->elems_[i]=static_cast<R>(other[i]); } } const R& operator[](std::size_t i) const { return this->elems_[i]; } R& operator[](std::size_t i) { return this->elems_[i]; } private: R elems_[N]; }; 

然后使用std::vector<ndpoint<...>>获得最佳性能的点集合。

唯一能够100%确定数据结构的方法是完全实现自己的内存处理。

但是,有很多库实现matrix和matrix操作,你可以检查出来。 一些已经logging了关于连续内存,重塑等信息(例如OpenCV Mat)。

请注意,一般来说,您不能相信一个Points 数组是连续的。 这是由于alignment,分配块头等。例如考虑

 struct Point { char x,y,z; }; Point array_of_points[3]; 

现在,如果您尝试“重塑”,也就是说,在Point元素之间进行迭代,以传递点在容器中相邻的事实 – 比最有可能失败的事实要多:

 (char *)(&array_of_points[0].z) != (char *)(&array_of_points[1].x)