2016-05-01 9 views
1

私はC++を学ぼうとしていますが、このコードの周りを頭で囲むことはできません。答え:printArray1でC++の基礎:forループとCスタイルの配列を関数に渡すためのレンジベース

#include <iostream> 

void printArray1(int (&array)[3]) { 
    for(int x : array) 
     std::cout << x << " "; 
} 

void printArray2(int array[]) { 
    for(int x : array) // compiler error, can't find begin and end 
     std::cout << x << " "; 
} 

int main() { 
    int a[3] = {34,12,88}; 

    for(int x : a) 
     std::cout << x << " "; 
    std::cout << std::endl; 

    printArray1(a); 
    printArray2(a); 
    std::cout << std::endl; 

    return 0; 
} 

、私たちは、これは我々が、アレイ全体のアドレスを受信して​​いるか、私達はちょうど最初にアドレスを受信して​​いる大きさ3の配列への参照を意味していているパラメータを受信して​​いますサイズ3の配列の要素ですか?また、このパラメータはどのようにループに渡されますか?

printArray2では、配列の最初の要素へのポインタを受け取っていますが、正しいですか?言い換えれば、printArray1のようなアドレスも受け取っていますか?したがって、配列のサイズデータがないため、この関数のレンジベースのforループはコンパイルされません。

最後に、遠隔ベースのforループをmainで印刷しようとすると、正確にループに渡されるのはどういうものでしょうか?それはここの配列の最初の要素へのポインタですか?その場合、なぜprintArray2のfor-loopがポインタを受け入れなかった場合にコンパイルされますか?

私のC++の理解はまだまだ基本的なので、本当に助けてくれてありがとう!

+0

あなたは自分のプログラムをデバッグして見ましたか?何が印刷されますか? –

答えて

2

範囲ベースのforループは、std::beginstd::endで使用できるすべてのタイプで機能します。

配列とポインタは同じではありません。配列は固定サイズを持ち、ポインタは固定サイズではありません。したがって、std::beginstd::endは配列に対しては機能しますが、ポインタに対しては機能しません。それはまた、range-based forループが1つの理由で動作する理由を説明しますが、もう一方は動作しません。

また、配列がポインタに崩壊することもあります。これは、たとえば、ポインタパラメータをとる関数に渡されたときに発生します。あるいは、不定サイズの配列パラメーター(ポインタパラメーターと事実上同じ)をとる関数に渡されたとき。それが起こると、サイズ情報が再び失われます。

したがって、関数の定義方法によって異なります。最初の関数は配列をとり、2番目の関数はポインタをとります。そのため、最初にサイズ情報が保持され、ループが機能します。

ただし、機能には制限があります。 2番目の関数はint b[2]を使用できますが、最初の関数は使用できません。printArray1arraysRanged-based for loop

約cppreferenceによれば

+0

したがって、基本的には、main()で_a_という識別子を使用すると、ループに配列型を渡していますか?しかし、_a_はまだポインタのような配列の最初の要素のアドレスですが、固定サイズを除いては、あなたが言ったように? – Joey

+0

「a」は、「配列の最初の要素へのアドレス」ではありません。 'a'は固定サイズの*配列です。あなたは配列とポインタを同じ型として考えるべきではありません。配列はアドレスとは関係がありません。唯一の関係は、配列が代入時のポインタに崩壊するかどうかです(変数に代入するか関数として渡すかパラメータ)。それについてもっと知るために配列の崩壊を調べてください。 –

+1

ああ、それで、範囲ベースのループに_a_を渡すときに配列に崩壊がないことと、最初の関数にパラメータが参照である_a_を渡すときに減衰がないと言うことは有効です、 はい? – Joey

0

の場合、この関数は配列がその型からどのくらい大きいかを知っています。参照はしばしば参照されるものへのポインタとして実装されますが、C++では実装の詳細(時には最適化を可能にする)を残すための長さがあります。参考文献は別名のデータで、ポインタ(ポストアドレスのようなもの)とは少し異なっています。コンパイラが長さを持つときは反復が簡単で、C++は正しいことを行います。

[]の場合、これはCスタイルの構文です。それは参照ではありません。それはint * arrayと同じ意味です。配列のサイズは、コンパイル時の型(関数内)の一部でもランタイム状態(単一のintポインタ)でもありません。明らかに反復は長さなしでは不可能です。

0

は、アレイ引数は、intの配列がを参照している各参照れるように渡される配列の最初の3つの値引数。 printArray2

アレイ引数は、引数として渡された配列の最初の値にポイントよりポインタです。これにより、配列のすべての値にアクセスできます。

最後に、これはポインタではなく、アレイの参照です。 この場合、重要なことは、反復ごとに反復された値のコピーがx変数に実行されることです。 これらのコピーがすべて発生しないようにするには、代わりに参照を宣言する必要があります。

例:

for(int &x : a) 
    std::cout << x << " "; 

ところで、あなたはまた、モダンなスタイルの配列ですarray containerを見て、取る必要があります。

関連する問題