2017-01-04 9 views
9

std::arrayの基になるraw(C)配列への参照を取得するには、どのような方法がありますか?std :: arrayからの生の配列への参照を取得する

data()メソッドは生のポインタだけを返します。これは不適切なポインタになります。既知のサイズの生の配列への参照を受け入れる関数に渡すためのものです。

また、data()が生のポインタを返し、基本となる生の配列への参照ではない、または単なる監視である理由がありますか?

+5

サイズの大きい配列への参照を渡すのは手間がかかり、広く使われていません。とにかく参照を持たないCコードと対話するために生の配列しか使用しないので、なぜでしょうか? – BoBTFish

+3

@WhiZTiM:OPは 'std :: array 'を' myFunc(int(&k)[5]) 'に渡すことができないことを意味します。 (5 intの配列への参照)。 –

+1

委員会が優れた選択肢として 'std :: array'を設計したからかもしれません。基になる生の配列への参照を簡単に取得できないようにすることは、私たちがプログラミングしたい方向に向かっているかもしれません。 – StoryTeller

答えて

13

std :: arrayの基本となるraw(C) 配列を取得する標準的な方法は何ですか?

基本となるC配列を取得する方法はありません。

はまた、なぜデータ()正当な理由がある生のポインタを返し、そして下層の生配列へない 参照、またはこれは単に見落としているのですか?

これは逆です:std::arrayが下位のC配列を提供する正当な理由はありません。すでに述べたように、C配列は関数がC配列への参照を取得する場合にのみ(生ポインタ上で)便利です。

void foo(int (&arr)[5]) 

ミー:

をするときは、機能を持っていた最後の時間でしたか?決して。私は、配列のサイズを取得(とポインタを拒否)を除いて、Cの配列参照パラメータを持つ関数を見たことがない:

template <class T, std::size_t N> 
auto safe_array_size(T (&)[N]) { return N; } 

をさんは、配列への参照が使用されていないパラメータ理由に少しダイブしてみましょう。

まず、C領域から、別のサイズパラメータを持つポインタが、配列間の崩壊と参照型の不足のために、配列を渡す唯一の方法でした。

C++には、std::vectorおよびstd::arrayのようなC配列の代替品があります。あなたがCの関数に渡す場合は、ポインタ+サイズ に立ち往生しているよう

  • あなたは、参照のオプションがありません:あなたは(レガシー)C配列を持っている場合でも、しかし、あなたは2つの状況を持っています
  • これをC++関数に渡したい場合、慣用的なC++の方法はbegin + endポインタを渡すことです。

最初に、begin + endイテレータは一般的なもので、あらゆる種類のコンテナを受け入れます。しかし、テンプレートを避けたい場合はstd::vectorへの参照を参照するのは珍しいことではありません。大きな欠点があるため、配列のサイズを知る必要があります。

void foo(int (&arr)[5]) 

これは非常に制限されています。

これを回避するには、そのテンプレートにする必要があります:あなたがより良いと行くので、テンプレートを回避する目的を打つ

template <std::size N> 
void foo(int (&arr)[N]) 

は+の代わりにテンプレートイテレータを終了し始めます。


いくつかの場合において

( 同じセマンティクスを有するわずか2または3の値に、例えば数学計算ので、それらは別々のパラメータであってはならない) 特定のアレイサイズが呼び出され、そして製造関数 は意味をなさないでしょう。そのような場合、配列のサイズを指定すると、 は、コンパイル時に正しいサイズの の配列だけを渡すことができるため、安全性が保証されます。したがって、それは有利だと 「大きな欠点」(Cおよび)C++の美しさの

一つではありません適用の巨大な範囲です。そう、はい、あなたは常に、独自の方法で特定の固有の機能を使用するか、必要とするフィールドを見つけるでしょう。あなたの例でも、私はまだ配列から恥ずかしがり屋だと言われています。意味的に分離してはならない固定数の値を持つときは、構造体が配列に対して正しい選択であると思います(例えば、float[4]の代わりにglm::mat4)。

しかし、std::arrayが何であるかを忘れないようにしましょう:Cアレイの現代的な代替品。オプションを分析するときに学んだことの1つは、絶対的な「より良い」ものがないということです。常に「依存」があります。しかし、この場合ではない:std::arrayは、インタフェースのC配列を間違いなく置き換えるべきである。したがって、固定サイズのコンテナが参照パラメータとして必要とされるまれなケースでは、既にstd::arrayがある場合にC配列の使用を推奨することはできません。そのため、基底のC配列std::arrayを公開する唯一の有効なケースは、C配列の参照パラメータを持つ古いライブラリです。しかし、私はこれをインターフェイスに加えると、より大きな画像ではそれが正当化されないと思います。新しいコードでは、構造体(std::tupleが各標準でより使いやすくなっています)またはstd::arrayを使用する必要があります。

+2

場合によっては(例えば、同じセマンティクスを持つちょうど2,3の値の数学計算のため、別々のパラメータではないはずです)、特定の配列サイズが求められ、意味をなさない。そのような場合、配列のサイズを指定すると、コンパイル時に正しいサイズの配列だけを渡すことができるため、安全性が保証されます。したがって、それは有利であり、 "大きな欠点"ではありません。 – Danra

+0

@Danra良い点があります。答えにあなたのコメントを統合しました。 – bolov

+2

私はちょうどC領域でさえも指摘したいと思います。[_pointer_を特定のサイズの配列にして、ほぼ同じ構文を使ってC++の特定のサイズの配列への参照を取ることは可能です] (http://rextester.com/MHUBK79249);残念なことに、異なるサイズの配列にポインタを渡すことは、私が知っているすべてのコンパイラのエラーではなく、警告として扱われます。 –

3

ありません。

特にレガシーコードを扱うときには、何十年も前のようなコードからイテレータ認識アルゴリズムに移行することになっています。そして、Cコードを使って作業するときは、とにかくポインタを使用する必要があります。私はこれらがこの機能性を提供しないという決定の要因であると推測します。

可能であれば、std::array<T, N>&を受け入れるようにコードを書き直してください。

関連する問題