42

C++ (C も同様) で変数を参照渡しする通常の方法は次のとおりです。

void _someFunction(dataType *name){ // dataType e.g int,char,float etc.
/****
definition
*/
}

int main(){
    dataType v;
    _somefunction(&v);  //address of variable v being passed
    return 0;
}

しかし、驚いたことに、参照によってオブジェクトを渡すときに、オブジェクト自体の名前が目的を果たし(&シンボルは不要)、関数の宣言/定義中に*引数の前にシンボルが必要ないことに気付きました。次の例は、それを明確にする必要があります。

// this
#include <iostream>
using namespace std;

class CDummy {
  public:
    int isitme (CDummy& param);     //why not (CDummy* param);
};

int CDummy::isitme (CDummy& param)
{
  if (&param == this) return true;
  else return false;
}

int main () {
  CDummy a;
  CDummy* b = &a;
  if ( b->isitme(a) )               //why not isitme(&a)
    cout << "yes, &a is b";
  return 0;
}

この特別な扱いが class で行われる理由を理解するのに問題があります。ほとんどクラスのような構造でさえ、このようには使用されません。配列の場合のように、オブジェクト名はアドレスとして扱われますか?

4

5 に答える 5

75

あなたを混乱させているように見えるのは、( を使用して&)参照渡しであると宣言されている関数が、実際のアドレスを使用して呼び出されない、つまり&a.

簡単な答えは、関数を参照渡しとして宣言することです。

void foo(int& x);

必要なのはそれだけです。その後、参照によって自動的に渡されます。

この関数を次のように呼び出します。

int y = 5;
foo(y);

y参照によって渡されます。

このようにすることもできます (しかし、なぜそうするのですか?マントラは:可能な場合は参照を使用し、必要な場合はポインターを使用します):

#include <iostream>
using namespace std;

class CDummy {
public:
    int isitme (CDummy* param);
};


int CDummy::isitme (CDummy* param)
{
    if (param == this) return true;
    else return false;
}

int main () {
    CDummy a;
    CDummy* b = &a;             // assigning address of a to b
    if ( b->isitme(&a) )        // Called with &a (address of a) instead of a
        cout << "yes, &a is b";
    return 0;
}

出力:

yes, &a is b
于 2013-08-09T13:12:04.673 に答える
19

参照は、実際には、味を良くするのに十分な砂糖を含むポインターです... ;)

ただし、ポインターとは異なる構文も使用するため、ポインターよりも参照を使用する方が少し簡単です。このため、ポインターを受け取る関数を呼び出すときは必要ありません&。コンパイラーがそれを処理します。*また、参照の内容を取得する必要はありません。

参照をエイリアスと呼ぶことは、かなり正確な説明です。それは「同じものの別の名前」です。したがって、aが参照として渡されるときは、実際aには のコピーではなくを渡していますa- のアドレスを渡すことによって (内部的に) 行われますがa、それがどのように機能するかについて心配する必要はありません [独自のしかし、独自のコンパイラを作成するときに知っておく必要のある楽しいことは他にもたくさんあります。プログラミングだけの場合は心配する必要はありません]。

int参照はまたはclassタイプに対して同じように機能することに注意してください。

于 2013-08-09T12:59:26.450 に答える
2

さて、参照渡しと値渡しを混同しているようです。また、C と C++ は異なる言語です。C は参照渡しをサポートしていません。

値渡しの C++ の例を 2 つ示します

// ex.1
int add(int a, int b)
{
    return a + b;
}

// ex.2
void add(int a, int b, int *result)
{
    *result = a + b;
}

void main()
{
    int result = 0;

    // ex.1
    result = add(2,2); // result will be 4 after call

    // ex.2
    add(2,3,&result); // result will be 5 after call
}

ex.1が呼び出されると、定数22は、スタック上にそれらのローカル コピーを作成することによって関数に渡されます。関数が戻ると、スタックは取り除かれ、スタック上の関数に渡されたものは事実上なくなります。

ex.2 でも同じことが起こりますが、今回は変数へのポインターintもスタックに渡されます。この関数は、このポインタ (単なるメモリ アドレス) を使用して、結果を「返す」ために、そのメモリ アドレスの値を逆参照および変更します。この関数はパラメータとしてメモリ アドレスを必要とするため、それを指定する必要があります。これ&は、 variable で「address-of」演算子を使用して行いますresult

参照渡しの 2 つの C++ の例を次に示します

// ex.3
int add(int &a, int &b)
{
    return a+b;
}

// ex.4
void add(int &a, int &b, int &result)
{
    result = a + b;
}

void main()
{
    int result = 0;

    // ex.3
    result = add(2,2); // result = 2 after call
    // ex.4
    add(2,3,result); // result = 5 after call
}

これらの関数は両方とも、最初の 2 つの例と同じ最終結果になりますが、違いは、呼び出し方法とコンパイラによる処理方法です。

まず、参照渡しがどのように機能するかを明確にしましょう。参照渡しでは、一般に、コンパイラの実装は、参照される変数にアクセスするために、最終的な実行可能ファイルで「ポインター」変数を使用します (または、コンセンサスのようです) が、これは真実である必要はありません。技術的には、コンパイラは、参照された変数のメモリ アドレスを直接置き換えるだけで済みます。これは、一般に信じられているよりも真実であると思われます。そのため、参照を使用すると、わずかではあるが実際にはより効率的な実行可能ファイルが生成される可能性があります。

次に、明らかに、参照渡しを使用する場合の関数の呼び出し方法は、値渡しと同じであり、関数内の元の変数に直接アクセスできるという効果があります。これは、呼び出し元から実装の詳細を隠すことによってカプセル化された結果です。欠点は、関数の外部で元の変数を変更せずに、渡されたパラメーターを変更できないことです。大きなオブジェクトをコピーする必要がないことによるパフォーマンスの向上が必要であるが、元のオブジェクトを変更したくない関数では、参照パラメーターの前にconst.

最後に、ポインター変数とは異なり、作成後に参照を変更することはできず、作成時に初期化する必要があります。

私がすべてをカバーし、それがすべて理解できたことを願っています.

于 2017-11-20T18:12:20.640 に答える
1

上記の場合の参照渡しはalias、実際のオブジェクトに対するものです。

別の名前で実際のオブジェクトを参照することになります。

referencesと比較して提供する多くの利点がありますpointer references

于 2013-08-09T12:53:35.513 に答える
0

追加しなければならないことの 1 つは、C には参照がないということです。

第二に、これは言語の構文規則です。& - アドレス演算子ですが、参照も意味します - すべてはユースケースに依存します

& の代わりに「参照」キーワードがあれば、次のように書くことができます

int CDummy::isitme (reference CDummy param)

しかし、これは C++ であり、長所と短所を受け入れる必要があります...

于 2013-08-09T13:18:10.607 に答える