web-dev-qa-db-ja.com

C ++関数シグネチャでの&演算子の使用

私は現在Accelerated C++を読んでいて、関数のシグネチャでの動作と動作が本当に理解していないことに気付きました。

int* ptr=#

ptrがnumへのアドレスを保持することを意味しますが、それはどういう意味ですか?

void DoSomething(string& str)

私が理解していることから、それは変数の参照によるパスです(つまり、アドレスを渡すことを意味します)が、

void DoSomething(string& str)
{
  string copy=str;
}

それが作成するのはstrのコピーです。変数にポインターを割り当てようとしているので、エラーが発生すると思いました。

ここで何が起きてるの?また、関数呼び出しで*および&を使用する意味は何ですか?

27
Ziv

参照はnotポインタであり、同じ目的を果たしますが異なります。参照は、別の変数、つまり同じアドレスを持つ2番目の変数のエイリアスと考えることができます。これにはアドレス自体は含まれず、初期化元の変数と同じメモリ部分参照のみが含まれます。

そう

string s = "Hello, wordl";
string* p = &s; // Here you get an address of s
string& r = s; // Here, r is a reference to s    

s = "Hello, world"; // corrected
assert( s == *p ); // this should be familiar to you, dereferencing a pointer
assert( s == r ); // this will always be true, they are twins, or the same thing rather

string copy1 = *p; // this is to make a copy using a pointer
string copy = r; // this is what you saw, hope now you understand it better.
35
unkulunkulu

& C++の文字は二重の目的です。それは(少なくとも)意味することができます

  1. 値のアドレスを取る
  2. 型への参照を宣言する

関数シグネチャで参照している用途は、#2のインスタンスです。パラメータstring& strstringインスタンスへの参照です。これは、関数のシグネチャに限定されるだけでなく、メソッド本体でも発生する可能性があります。

void Example() {
  string s1 = "example";
  string& s2 = s1;  // s2 is now a reference to s1
}

C++ FAQエントリのリファレンスを参照することをお勧めします。

26
JaredPar

Accelerated C++の第10章に到達するまで、ポインタについてanythingを知らないでください!

参照は、別の場所に存在するものの別名、別名を作成します。それでおしまい。隠されたポインタやアドレスは含まれていません。カーテンの後ろを見ないでください!

ロバートという名前の男を考えてください

guy   Robert;

時には彼をボブと呼びたいかもしれません

guy& Bob = Robert;

今、ボブとロバートはどちらも同じ人を指しています。あなたは彼の住所(または電話番号)を取得せず、同じものの別の名前を取得します。

あなたの機能で

void DoSomething(string& str)
{
  string copy=str;
}

まったく同じように機能し、strは他の場所に存在する文字列の別名です。

それがどのように行われるか気にしないでください、参照をあるオブジェクトの名前と考えてください。コンパイラーは名前を接続する方法を理解する必要がありますが、そうする必要はありません。

13
Bo Persson

変数を割り当てる場合(つまり、int* ptr = &value)、アンパサンドを使用すると、変数のaddressが返されます(この場合、valueのアドレス)。

関数パラメーターでアンパサンドを使用すると、変数のメモリ内の同じ物理領域にアクセスまたは参照を渡すことになります(使用しない場合は、代わりにコピーが送信されます)。パラメーターの一部としてアスタリスクを使用する場合は、変数ポインターを渡すことを指定しているため、ほぼ同じことが実現されます。ここでの違いは、アンパサンドを使用すると、名前を介して変数に直接アクセスできることですが、ポインターを渡す場合、実際の値を取得して操作するには、ポインターをdeferenceにする必要があります:

void increase1(int &value) {
   value++;
}

void increase2(int *value) {
   (*value)++;
} 

void increase3(int value) {
   value++;
}

ご了承ください increase3はコピーのみが送信されるため、渡した元の値には何もしません。

int main() {
   int number = 5;
   increase1(number);
   increase2(&number);
   increase3(number);
   return 0;
}

3つの関数呼び出しの最後のnumberの値は8ではなく7です。

11
Manny D

これは、変更が関数に渡される文字列に影響を与えない通常の文字列パラメーターとは異なり、関数が渡された文字列を変更できるようにする参照です。

内部で参照が文字列のコピーを作成しないため、パフォーマンスの目的で行われるconst string&型のパラメーターがよく見られます。

4
pezcode
int* ptr=#

1番目のケース:ptrはメモリであり、変数のアドレスを格納するため。 &演算子は、メモリ内のnumのアドレスを返します。

void DoSomething(string& str)

2番目のケース:アンパサンド演算子は、変数が参照によって渡されており、関数によって変更できることを示すために使用されます。

したがって、基本的に&演算子には、コンテキストに応じて2つの関数があります。

2
Pepe

参照渡しは、アドレスをポインターとして渡すことでコンパイラーによって実装できますが、意味的には、アドレスまたはポインターとは関係ありません。簡単に言えば、これは単に変数のエイリアスです。

C++には、構文が異なるセマンティクスの異なるコンテキストで再利用されるケースがたくさんありますが、これはそれらのケースの1つです。

1
jk.

の場合:

int* ptr=#

ptrという名前の変数をint *(intポインター)の型で宣言し、その値を「変数numのアドレス」(&num)に設定しています。 「addressof」演算子(&)はポインタを返します。

の場合:

void DoSomething(string& str)

doSomething()メソッドの最初のパラメーターを "文字列への参照"型として宣言しています。事実上、これは「参照渡し」を定義するC++の方法です。

これらの場合、&演算子はsimilarlyを操作しますが、同じように機能しないことに注意してください。具体的には、演算子として使用すると、指定した変数のアドレスを取得するようコンパイラーに指示することになります。メソッドシグネチャで使用すると、引数が参照であることをコンパイラに伝えます。また、「参照としての引数」ビットは、ポインタである引数を持つこととは異なります。参照引数(&)は自動的に逆参照され、基礎となるデータが格納されている場所に関してメソッドに公開されることはありません。ポインター引数を使用すると、参照で渡されますが、変数が格納されているメソッドに公開され、メソッドが逆参照に失敗した場合に問題が公開される可能性があります(これは、思ったよりも頻繁に発生します)。

1
Paul Sonier

copyからstrを暗黙的にコピー構築しています。はい、strは参照ですが、それから別のオブジェクトを作成できないという意味ではありません。 c ++では、&演算子は次の3つのいずれかを意味します-

  1. 通常の参照variableを定義する場合、オブジェクトにaliasを作成します。
  2. これを関数パラメーターで使用すると、参照によって渡されますとなります-コピーに並置されるように、オブジェクトのエイリアスも作成しています。この場合、基本的にisに渡されたオブジェクトであるため、違いはありません。 does渡すオブジェクトにポインタなどが含まれている場合に違いがあります。
  3. &の最後の(そしてほとんどの場合は無関係な)意味は、ビット単位のANDです。

参照について(少し正しくはありませんが)別の考え方は、逆参照されたポインターの構文糖衣です。

0
Seb Holzapfel