访问向量<vector <int>&gt;作为一个平面数组</vector <int>

时间:2012-10-20 22:53:42

标签: c++ vector std multidimensional-array flat

对于这个数组:

vector<vector<int> > v;

v.push_back(vector<int>(0));
v.back().push_back(1);
v.back().push_back(2);
v.back().push_back(3);
v.back().push_back(4);

我可以很容易地输出{1,2,3,4}:

cout << v[0][0] << endl;
cout << v[0][1] << endl;
cout << v[0][2] << endl;
cout << v[0][3] << endl;

要以平面阵列的形式访问它,我可以这样做:

int* z = (int*)&v[0].front();

cout << z[0] << endl;
cout << z[1] << endl;
cout << z[2] << endl;
cout << z[3] << endl;

现在,如何将多维向量作为平面多维数组进行访问?我不能使用与访问一维向量相同的格式:

// This does not work (outputs garbage)
int** n = (int**)&v.front();

cout << n[0][0] << endl;
cout << n[0][1] << endl;
cout << n[0][2] << endl;
cout << n[0][3] << endl;

我发现的解决方法是这样做:

int** n = new int* [v.size()];

for (size_t i = 0; i < v.size(); i++) {
   n[i] = &v.at(i).front();
}

cout << n[0][0] << endl;
cout << n[0][1] << endl;
cout << n[0][2] << endl;
cout << n[0][3] << endl;

是否有办法访问整个多维向量,如平面c样式数组,而无需在访问数据之前动态分配数据上方的每个维度?

速度在实施中并不重要,维护的清晰度至关重要。多维向量适合存储数据。但是,我还希望在SDK中将数据公开为平面c样式数组,以便其他语言可以轻松访问它。这意味着将向量公开为STL对象是不行的。

我提出的解决方案可以很好地满足我的需求,因为我只在处理结束时对数组进行一次评估,以“压平”它。但是,还有更好的方法吗?或者我已经在没有重新实现我自己的数据结构的情况下以最好的方式做到了(因为我的扁平化代码只有几行而过度杀伤)。

感谢您的建议,朋友们!

4 个答案:

答案 0 :(得分:3)

vector的缓冲区通常是动态分配的。

这意味着当你有一个vector vector时,那么关于内部缓冲区,你有一些类似于指针数组的东西,每个指针都指向一个数组。

如果你需要在相同数据的1D和2D视图之间切换,最简单的可能就是定义一个2D数组类,就像这样(关闭袖口):

typedef ptrdiff_t Size;
typedef Size Index;

template< class Item >
class Array2D
{
private:
    std::vector< Item > items_;
    Size                width_;
    Size                height_;

    Index indexFor( Index const x, Index const y )
    { return y*width_ + x; }

public:
    Size width() const { return width_; }
    Size height() const { return height_; }

    Item& operator()( Index const x, Index const y )
    { return items_[indexFor( x, y )]; }

    Item const& operator()( Index const x, Index const y ) const
    { return items_[indexFor( x, y )]M; }

    Size bufferSize() const { return width_*height_; }
    Item* buffer() { return &items_[0]; }
    Item const* buffer() const { return &items_[0]; }

    Array2D( Size const w, Size const h )
        : items_( w*h )
        , width_( w )
        , height_( h )
    {}
};

然后你可以做像

这样的事情
Array2D< int >  a( 4, 3 );

for( Index y = 0;  y < a.height();  ++y )
{
    for( Index x = 0;  x < a.width();  ++x )
    {
        foo( a( x, y ) );
    }
}

Array2D< int >  a( 4, 3 );

int* const pb = a.buffer();
for( Index i = 0;  i < a.bufferSize();  ++i )
{
    foo( pb[i];
}

答案 1 :(得分:0)

  

现在,如何将多维向量作为平面多维数组进行访问?

你不能。

您可以vector<int>作为int[]访问的原因是因为布局相同。 vector<vector<int>>的内存布局与int*[]的布局不同,这意味着您无法像int*[]那样访问它。

如果你无法避免通过int*[]访问数据那么你正在做什么,分配一个int*数组并用指针填充它来填充它是你能做的最好的。如果你可以在第一时间避免需要这样做会更好。

您可能希望为int*[]使用例外安全持有者。您也可能不需要使用vector::at(),您可能会考虑是否需要处理其中一个向量为空的情况。在这里,我使用C ++ 11功能解决了这些问题。

std::unique_ptr<int*[]> n(new int* [v.size()]);
transform(begin(v), end(v), n.get(), [](std::vector<int> &i) { return i.data(); });

答案 2 :(得分:0)

嗯,你不能因为虽然向量可以保证将它们的元素存储在连续的内存中,但是向量向量并不能保证与2D C风格的数组相同的存储布局。

所以不,这是不可能的,而且我会更进一步说int* z = (int*)&v[0].front();只是丑陋。

答案 3 :(得分:0)

如果你的1d向量(std::vector<int>)大小相同 - 那么保留在向量原始数组中:

typedef int ARRAY[6];
std::vector<ARRAY> yourVector; 

如果它们的大小不相同 - 那么你就有问题,因为每个std::vector<int>占用了连续的内存区域,但这些区域不是连续的。与原始C数组完全相同:

int** a = new int*[3];
a[0] = new int[4];
a[1] = new int[5];

a并未指向大小为(4+5)*sizeof(int)的连续内存...