简体   繁体   English

如何转换向量 <vector<int> &gt; int **而无需重建数组?

[英]How to convert a vector<vector<int>> to int** without rebuilding the array?

I don't like to use pointers too much and I'm always using stl tools. 我不太喜欢使用指针,而且我总是使用stl工具。 I've gotten into this situation where I need to pass a int** to a third_party function that needs to work with a 2d array of ints. 我陷入了这种情况,我需要将int **传递给需要使用2d数组int的third_party函数。 I have written the following function that creates a vector of int*s to do the job. 我编写了以下函数,该函数创建一个int * s向量来完成这项工作。 My question is that is it safe to do this assuming that the third_party function does not change the structure of the array and just accesses the data entries. 我的问题是,假设third_party函数不更改数组的结构并且仅访问数据条目,这样做是否安全? Is there a better way to do this? 有一个更好的方法吗?

Here is the function def: 这是函数def:

void ConvertVectorVectorToIntStarStar(const std::vector<std::vector<int> >& v,vector<int*>* a) {
  assert(a);
  int n = v.size();
  a->resize(n);
  for(int i = 0; i < n; ++i)
    (*a)[i] = (int*)(&v[i][0]);
}

and this is the usage: 这是用法:

  vector<int*> p;
  ConvertVectorVectorToIntStarStar(v, &p);
  int** a = &p[0];
  third_party_function(a);

How to convert a vector<vector<int>> to int** 如何将vector<vector<int>>转换为int**

You can't simply convert it. 您不能简单地将其转换。

The internal layout of a vector of vector<int> is just mind-bogglingly incompatible with an array of int* . vector<int>vector<int>的内部布局与int*数组令人难以置信地不兼容。 :-) :-)

Here are your types: 这是您的类型:

vector<vector<int>> v{{ 1, 2, 3 }, { 1, 2, 3 }, { 1, 2, 3 } };
int (*a)[] = { new int[3], new int[3], new int[3] };

The first thing you'll notice is that a is an int (*)[] rather than an int** . 您会注意到的第一件事是aint (*)[]而不是int** When you use a it'll decay to an int** ; 当使用a它将衰减为int** an int[][] would not do this . int[][] 不会这样做

Let's get our first-level pointers: 让我们获取一级指针:

vector<int>* ptr1 = &v[0];
int**        ptr2 = &a[0];

Now let's look at the storage: 现在让我们看一下存储:

  • ptr1[0] is a vector<int> ptr1[0]vector<int>
  • ptr2[0] is a int* ptr2[0]是一个int*

Clearly, these are not in any way the same sort of thing. 显然,这些绝不是同一件事。 Without even needing to go any further, the memory layout is already different. 甚至无需进一步操作,内存布局就已经不同。 This means you cannot just "get" an int** to the vector's data. 这意味着您不能只是“获取”向量数据的int**


However , if you don't mind constructing the outermost "indexing" array from scratch, then your approach is basically sound. 但是 ,如果您不介意从头开始构建最外面的“索引”数组,那么您的方法基本上是正确的。 It's just not the zero-step process you seem to be after. 这似乎不是您要遵循的零步骤流程。


Instead of all this, my suggestion would be wrapping a vector<int> (with length Width × Height) with 2D-index access semantics. 代替所有这些,我的建议是使用二维索引访问语义包装vector<int> (长度Width×Height)。 You would then be able to play with an int* to the entire data buffer if you wished. 然后,您可以根据需要对整个数据缓冲区使用int*

With thanks to Freenode ##c++ : 感谢Freenode ## c ++

template<typename T>
struct matrix
{
   matrix(unsigned m, unsigned n)
      : m(m), n(n), vs(m*n)
   {}

   T& operator()(unsigned i, unsigned j)
   {
      return vs[i + m * j];
   }

private:
   unsigned m, n;
   std::vector<T> vs;
};

/* column-major/opengl: vs[i + m * j], row-major/c++: vs[n * i + j] */

If you need the cast, something isn't right: 如果需要演员表,那是不对的:

(*a)[i] = (int*)(&v[i][0]);

I guess this should really read 这应该真的读

(*a)[i] = const_cast<int*>(v[i].data());

Otherwise the code looks OK and it should work: the elements in a std::vector<T> are contiguous. 否则,代码看起来就可以正常工作了: std::vector<T>中的元素是连续的。

Instead of the current code … 代替当前代码...

void ConvertVectorVectorToIntStarStar(const std::vector<std::vector<int> >& v,vector<int*>* a) {
  assert(a);
  int n = v.size();
  a->resize(n);
  for(int i = 0; i < n; ++i)
    (*a)[i] = (int*)(&v[i][0]);
}

I suggest that you do … 我建议你做……

vector<int*> IntStarStarFrom( std::vector<std::vector<int>>& v)
{
    int const n = static_cast<int>( v.size() );
    assert( n > 0 );
    vector<int*> a( n );

    for(int i = 0; i < n; ++i)
    {
        assert( v[i].size() > 0 );
        a[i] = &v[i][0];
    }
    return std::move( a );
}

Disclaimer: off-the cuff code, not touched by compiler's hands. 免责声明:现成的袖珍代码,不会被编译器之手触及。

The assertions express the relevant safety concerns. 这些断言表达了相关的安全问题。

A vector's buffer is guaranteed contiguous, but IIRC it's Undefined Behavior to index the vector when its size is 0. 保证向量的缓冲区是连续的,但是IIRC在其大小为0时对向量进行索引是未定义行为。

The usage code, reworked to use the suggested function replacement: 修改了用法代码以使用建议的功能替换:

vector<int*> p = IntStarStarFrom( v );
int** const a = &p[0];
third_party_function( a );

Or as Mark Ransom remarked in a comment, you can now do this in a single line of code: 或如Mark Ransom在评论中所述,您现在可以在一行代码中完成此操作:

third_party_function(IntStarStarFrom(v).data());
std::vector<std::vector<int> > vt;
// some code with vt..

std::vector<int *> vtp;
for (const std::vector<int> &vtr : vt)
    vtp.push_back(const_cast<int *>(vtr.data()));

I haven't tested but I think I works well 我还没有测试,但我认为我做得很好

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM