簡體   English   中英

如何處理C ++中的數組(在堆棧上聲明)?

[英]How to deal with arrays (declared on the stack) in C++?

我有一個類來解析一個矩陣,將結果保存在數組成員中:

class Parser
{
  ...
  double matrix_[4][4];
};

這個類的用戶需要調用一個API函數(例如,我無法控制的函數,所以我不能只是改變它的界面以使事情更容易工作),如下所示:

void api_func(const double matrix[4][4]);

我讓調用者將數組結果傳遞給函數的唯一方法是將成員公開:

void myfunc()
{
  Parser parser;
  ...
  api_func(parser.matrix_);
}

這是做事的唯一方法嗎? 我對這樣聲明的多維數組的不靈活性感到震驚。 我認為matrix_基本上與double**相同,我可以(安全地)在兩者之間施放。 事實證明,我甚至找不到一種不安全的方式在事物之間施放。 假設我添加了一個Parser類的訪問器:

void* Parser::getMatrix()
{
  return (void*)matrix_;
}

這將編譯,但我不能使用它,因為似乎沒有辦法轉回到怪人數組類型:

  // A smorgasbord of syntax errors...
  api_func((double[][])parser.getMatrix());
  api_func((double[4][4])parser.getMatrix());
  api_func((double**)parser.getMatrix()); // cast works but it's to the wrong type

錯誤是:

錯誤C2440:'type cast':無法從'void *'轉換為'const double [4] [4]'

......有一個有趣的附錄:

雖然存在對引用或指向數組的指針的轉換,但是沒有對數組類型的轉換

我無法確定如何轉換為引用或指向數組的指針,盡管它可能對我沒有幫助。

可以肯定的是,在這一點上,這個問題純粹是學術性的,因為void*演員陣容並不比一個單獨的集體成員更公開!

這是一個很好,干凈的方式:

class Parser
{
public:
   typedef double matrix[4][4];

   // ...

   const matrix& getMatrix() const
   {
      return matrix_;
   }

   // ...

private:
  matrix matrix_;
};

現在您正在使用描述性類型名稱而不是數組,但由於它是一個typedef ,編譯器仍然允許將其傳遞給采用基本類型的不可更改的API函數。

試試這個。 它在gcc 4.1.3上完全編譯:

typedef double FourSquare[4][4];

class Parser
{
  private:
    double matrix_[4][4];

  public:
    Parser()
    {
        for(int i=0; i<4; i++)
          for(int j=0; j<4; j++)
            matrix_[i][j] = i*j;
    }

  public:
    const FourSquare& GetMatrix()
    {
        return matrix_;
    }
};

void api_func( const double matrix[4][4] )
{
}

int main( int argc, char** argv )
{
    Parser parser;
    api_func( parser.GetMatrix() );
    return 0;
}

我曾經使用像這樣的聯盟來傳遞過去的矩陣:

union matrix {
    double dflat[16];
    double dmatr[4][4];
};

然后將指針傳遞給setter並將數據復制到類中的矩陣中。

有辦法處理這個問題(更通用),但根據我的經驗,這個解決方案往往是最干凈的。

我認為matrix_基本上和雙**一樣

在C中有真正的多維數組,而不是指向數組的指針數組,因此double [4] [4]是四個double [4]數組的連續數組,相當於double [16],而不是a(double) *)[4]。

沒有對數組類型的轉換,盡管有引用轉換或指向數組的指針將值轉換為double [4] [4]會嘗試在堆棧上構造一個 - 相當於std :: string(parser.getMatrix( )) - 除了數組不提供合適的構造函數。 你可能不想這樣做,即使你可以。

由於類型對步幅進行編碼,因此需要完整類型(double [] []不會這樣做)。 您可以重新解釋將void *轉換為((d​​ouble [4] [4])*),然后獲取引用。 但是最簡單的方法是輸入矩陣並首先返回正確類型的引用:

typedef double matrix_t[4][4];

class Parser
{
    double matrix_[4][4];
public:
    void* get_matrix () { return static_cast<void*>(matrix_); }

    const matrix_t& get_matrix_ref () const { return matrix_; }
};

int main ()
{
    Parser p;

    matrix_t& data1 = *reinterpret_cast<matrix_t*>(p.get_matrix());

    const matrix_t& data2 = p.get_matrix_ref();
}

要詳細說明所選答案,請遵守此行

const matrix& getMatrix() const

這很棒,你不必擔心指針和鑄造。 您將返回對基礎矩陣對象的引用 恕我直言參考是C ++的最佳功能之一,我在直接C編碼時錯過了。

如果您不熟悉C ++中引用和指針之間的區別, 請閱讀此內容

無論如何,你必須要注意,如果實際擁有底層矩陣對象的Parser對象超出范圍,那么任何試圖通過該引用訪問矩陣的代碼現在將引用一個超出范圍的對象,你會崩潰

暫無
暫無

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

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