2

For this array:

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);

I can output {1, 2, 3, 4} easily enough:

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

To access it as a flat array I can do this:

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

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

Now, how do I access the multidimensional vector as a flat multidimensional array? I cannot use the same format as accessing a single-dimensional vector:

// 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;

The workaround I've found is to do this:

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;

Is there a way to access the entire multidimensional vector like a flat c-style array without having to dynamically allocate each dimension above the data before accessing it?

Speed is not critical in the implementation and clarity for maintenance is paramount. A multidimensional vector is just fine for storing the data. However, I want to also expose the data as a flat c-style array in the SDK so that it can be easily accessible by other languages. This means that exposing the vectors as an STL object is a no go.

The solution I came up with works fine for my needs as I only evaluate the array once at the very end of processing to "flatten" it. However, is there a better way to go about this? Or am I already doing it the best way I possibly can without re-implementing my own data structure (overkill since my flatten code is only a few lines).

Thank you for your advice, friends!

4

4 回答 4

3

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

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

如果您需要在相同数据的 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];
}
于 2012-10-20T23:08:43.873 回答
0

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

你不能。

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

如果您无法避免通过 a 访问数据,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(); });
于 2012-10-20T23:00:32.783 回答
0

好吧,你不能,因为尽管向量可以保证将它们的元素存储在连续的内存中,但向量的向量并不能保证与 2D C 样式数组相同的存储布局。

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

于 2012-10-20T23:00:50.330 回答
0

如果您的一维向量 ( 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)......

于 2012-10-20T23:01:21.377 回答