web-dev-qa-db-ja.com

ベクトルを関数に渡す、値と参照のC ++

私はC++でコーディングしています。関数void foo(vector<int> test)があり、プログラムで呼び出す場合、ベクトルは値または参照で渡されますか?ベクトルと配列が似ていること、およびvoid bar(int test[])のような関数が値ではなく参照(ポインター?)でテストを渡すことを知っているので、私は確信していません。私の推測では、値による受け渡しを避けたい場合、ポインタ/参照によってベクトルを明示的に渡す必要がありますが、よくわかりません。

69
Adam

推測しなければならない場合、あなたはJavaのバックグラウンドから来ていると言えます。これはC++であり、&- operatorを使用して別の方法で指定しない限り、値によって値が渡されます(この演算子は 'address-of'演算子としても使用されますが、異なるコンテキストで使用されます)。これはすべて十分に文書化されていますが、とにかく繰り返します:

void foo(vector<int> bar); // by value
void foo(vector<int> &bar); // by reference (non-const, so modifyable inside foo
void foo(vector<int> const &bar); // by const-reference

ポインタをベクトル(void foo(vector<int> *bar))に渡すこともできますが、自分が何をしているのかがわかっていて、これが本当に正しい方法だと思わない限り、これをしないでください。

また、ベクトルはnot配列と同じです!内部的に、ベクターはメモリ管理を処理する配列を追跡しますが、他の多くのSTLコンテナーも同様です。ポインターまたは配列を期待する関数にベクトルを渡すことはできません(逆も同様です)(基になる配列へのアクセス(ポインター)を取得し、これを使用できます)。ベクトルはメンバー関数を介して多くの機能を提供するクラスですが、ポインターと配列は組み込み型です。また、ベクトルは動的に割り当てられ(実行時にサイズが決定および変更される可能性があることを意味します)、Cスタイルの配列は静的に割り当てられ(サイズは一定であり、コンパイル時に認識される必要があります)、その使用を制限します。

C++全般について詳しく読むことをお勧めします(具体的には array decay )。次に、配列とポインターの違いを示す次のプログラムをご覧ください。

void foo1(int *arr) { cout << sizeof(arr) << '\n'; }
void foo2(int arr[]) { cout << sizeof(arr) << '\n'; }
void foo3(int arr[10]) { cout << sizeof(arr) << '\n'; }
void foo4(int (&arr)[10]) { cout << sizeof(arr) << '\n'; }

int main()
{
    int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    foo1(arr);
    foo2(arr);
    foo3(arr);
    foo4(arr);
}
94
JorenHeit

vectorは機能的には配列と同じです。しかし、言語にとってvectorは型であり、intも型です。関数の引数に対して、任意の型の配列(vector[]を含む)はポインターとして扱われます。 vector<int>は、(コンパイラにとって)int[]と同じではありません。 vector<int>は非配列、非参照、および非ポインターです。値で渡されるため、コピーコンストラクターを呼び出します。

したがって、vector<int>&を使用して(関数が変更しない場合はconstを使用するのが望ましい)、参照として渡す必要があります。

15
Ajay

void foo(vector<int> test)

この場合、ベクトルは値で渡されます。

コンテキストに応じてベクトルを渡す方法は他にもあります。

1)参照渡し:-これにより、関数fooがベクトルの内容を変更できます。ベクトルのコピーが回避されるため、値渡しよりも効率的です。

2)const-referenceによる受け渡し:-関数がベクトルの内容を変更したくない場合、これは効率的で信頼性があります。

8
ravi