簡體   English   中英

如何轉換向量 <vector<int> &gt; int **而無需重建數組?

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

我不太喜歡使用指針,而且我總是使用stl工具。 我陷入了這種情況,我需要將int **傳遞給需要使用2d數組int的third_party函數。 我編寫了以下函數,該函數創建一個int * s向量來完成這項工作。 我的問題是,假設third_party函數不更改數組的結構並且僅訪問數據條目,這樣做是否安全? 有一個更好的方法嗎?

這是函數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]);
}

這是用法:

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

如何將vector<vector<int>>轉換為int**

您不能簡單地將其轉換。

vector<int>vector<int>的內部布局與int*數組令人難以置信地不兼容。 :-)

這是您的類型:

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

您會注意到的第一件事是aint (*)[]而不是int** 當使用a它將衰減為int** int[][] 不會這樣做

讓我們獲取一級指針:

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

現在讓我們看一下存儲:

  • ptr1[0]vector<int>
  • ptr2[0]是一個int*

顯然,這些絕不是同一件事。 甚至無需進一步操作,內存布局就已經不同。 這意味着您不能只是“獲取”向量數據的int**


但是 ,如果您不介意從頭開始構建最外面的“索引”數組,那么您的方法基本上是正確的。 這似乎不是您要遵循的零步驟流程。


代替所有這些,我的建議是使用二維索引訪問語義包裝vector<int> (長度Width×Height)。 然后,您可以根據需要對整個數據緩沖區使用int*

感謝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] */

如果需要演員表,那是不對的:

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

這應該真的讀

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

否則,代碼看起來就可以正常工作了: std::vector<T>中的元素是連續的。

代替當前代碼...

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

我建議你做……

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

免責聲明:現成的袖珍代碼,不會被編譯器之手觸及。

這些斷言表達了相關的安全問題。

保證向量的緩沖區是連續的,但是IIRC在其大小為0時對向量進行索引是未定義行為。

修改了用法代碼以使用建議的功能替換:

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

或如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()));

我還沒有測試,但我認為我做得很好

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM