2016-12-18 14 views
-1

配列の値を関数に渡すとき、C++コンパイラ は、配列の名前(配列が始まるアドレス)を関数 に渡します。なぜC++コンパイラは配列の内容全体ではなく、 配列の名前だけを関数に渡すのですか?関数に渡す配列

+0

このように言語が定義されている理由についての説明は、一般的なコンピューティングの歴史と特にこのサイトでは広すぎるプログラミング言語に関する論文です。 –

答えて

0

あなたの質問は間違っています。あなたが機能ffooの名前を渡していない

int foo[5] = {1,2,3,4,5}; 
f(foo); 

を書くとき、あなたはfooの最初の要素へのポインタを渡しています。関数fint*を得ており、intの大きさを知っているので、2番目、3番目、4番目の要素を探すためにどのくらい先にメモリにあるのかを知っています。これは配列を実装するための最小の最小値なので、それが普及した理由です。

C++ 11では、大きさを知る配列を渡すには、std::arrayを使用します。これは、それがどのように大きな知っている配列である:

#include <array> 
std::array<int, 5> foo {1,2,3,4,5}; 

f(foo); 

foo[42] = 1; // compile-time error! 

あなたはそれがarrayがどのように大きな知っているようf記述する必要があるしかし:

void f(const std::array<int, 5>& ai); // this works 

またはそれをテンプレートにし、それがいずれかを取ることができるようにしますサイズアレイ:

template<size_t Size> 
void f(const std::array<int, Size>& ai); 

(または任意のタイプのアレイも:)

template<typename T, size_t Size> 
void f(const std::array<T, Size>& a); 

または、std::vectorにデータを格納します。彼らは時々std::arrayや、組み込み配列よりも効率だが、多くの、より柔軟:

std::vector<int> foo {1,2,3,4,5}; 
f(foo); 

... 

void f(const std::vector<int>& foo); 
1

「なぜ」簡単です。それが標準が言うものだからです。

[§4.2 ¶ 1]

タイプの左辺または右辺値「N Tの配列」または「Tの を結合し、未知の配列は、」タイプ「Tへのポインタ」のprvalueに変換することができます。 一時的なマテリアライゼーション変換([conv.rval])が適用されます。 結果は配列の最初の要素へのポインタです。単一の名前が単一 範囲にいくつかの異なる機能のために使用することができる

[§8.3.5 ¶ 5]

。これは関数のオーバーロードです(Clause [over])。関数のすべての宣言 は、戻り型とパラメータ型リストの両方で正確に一致しなければならない。関数のタイプは、規則に従って を使用して決定されます。各パラメータのタイプ(ファンクションパック を含む)は、それ自身のdecl-specifier-seqと 宣言子から決定されます。各パラメータのタイプを決定した後、タイプ "array of T"または関数タイプTの パラメータは "Tへのポインタ"に調整されます。パラメータタイプのリストを生成した後、 ファンクションタイプを構成するときに、パラメータタイプを変更する最上位のcv修飾子 が削除されます。変換されたパラメータ のタイプの結果のリストと、省略記号またはファンクションパックの有無は、ファンクションのパラメータタイプリストです。 [注:この 変換はパラメータの種類には影響しません。 の例では、int(*)(const int p, decltype(p)*)int(*)(int, const int*) は同じタイプです。 - エンドノート]

関連する問題