web-dev-qa-db-ja.com

const参照と通常のパラメーターの違い

void DoWork(int n);
void DoWork(const int &n);

違いは何ですか?

45

大きな構造体/クラスを渡す場合、違いはより顕著になります。

struct MyData {
    int a,b,c,d,e,f,g,h;
    long array[1234];
};
void DoWork(MyData md);
void DoWork(const MyData& md);

use 'normal'パラメーターを使用する場合、値でパラメーターを渡すため、渡すパラメーターのコピーを作成します。 const参照を使用している場合、参照渡しし、元のデータはコピーされません。

どちらの場合も、関数内から元のデータを変更することはできません。

編集:
場合によっては、元のデータが answerCharles Bailey で指摘されているように変更される可能性があります。

54
Afriza N. Arief

重要な違いは、const参照で渡す場合、新しいオブジェクトは作成されないことです。関数本体では、パラメーターは事実上、渡されたオブジェクトのエイリアスです。

参照はconst参照であるため、関数本体はそのオブジェクトの値を直接変更できません。これは、値で渡すのと同様のプロパティを持ち、関数本体も渡されたオブジェクトの値を変更できません。この場合、パラメーターはコピーであるためです。

重要な違いがあります。パラメータがconst参照であるが、渡されたオブジェクトが実際にconstでない場合、オブジェクトの値は関数呼び出し中に変更される可能性があります。

例えば。

int a;

void DoWork(const int &n)
{
    a = n * 2;  // If n was a reference to a, n will have been doubled 

    f();  // Might change the value of whatever n refers to 
}

int main()
{
    DoWork(a);
}

また、渡されたオブジェクトが実際にconstでなかった場合、関数は(不適切なアドバイスであっても)キャストで値を変更できます。

例えば.

void DoWork(const int &n)
{
    const_cast<int&>(n) = 22;
}

渡されたオブジェクトが実際にconstである場合、これは未定義の動作を引き起こします。

パラメーターがconst参照によって渡される場合、追加のコストには逆参照、オブジェクトの局所性の悪化、コンパイルの最適化の機会の減少が含まれます。

パラメーターが値で渡され、追加のコストがパラメーターコピーを作成する必要がある場合。通常、これはオブジェクトタイプが大きい場合にのみ問題になります。

53
CB Bailey

関数に値を渡すことができる3つの方法があります

  1. 値渡し

    void f(int n){
        n = n + 10;
    }
    
    int main(){
        int x = 3;
        f(x);
        cout << x << endl;
    }
    

    出力:3.欠点:パラメーターxf関数を通過すると、コンパイラーはxのメモリー内にコピーを作成します。だからメモリの浪費。

  2. 参照渡し

    void f(int& n){
        n = n + 10;
    }
    
    int main(){
        int x = 3;
        f(x);
        cout << x << endl;
    }
    

    出力:13.値渡しによる不利な点を排除しますが、プログラマーが値を変更したくない場合は、定数参照を使用します

  3. 定数リファレンス

    void f(const int& n){
        n = n + 10; // Error: assignment of read-only reference  ‘n’
    }
    
    int main(){
        int x = 3;
        f(x);
        cout << x << endl;
    }
    

    出力:n = n + 10でエラーをスローします。const参照パラメーター引数を渡すと読み取り専用パラメーターになり、nの値を変更できないためです。

12
sneha

 void DoWork(int n);

nは実際のパラメーターの値のコピーであり、関数内でnの値を変更することは正当です。と

void DoWork(const int &n);

nは実際のパラメーターへの参照であり、その値を変更することはできません。

6
Avi

Constキーワードについて何も言及していないので...

constキーワードは、型宣言の型または関数パラメーターの型を変更し、値が変化しないようにします。 (情報源:MS)

つまり、パラメーターを参照渡しすると、呼び出し先による変更にさらされます。 constキーワードを使用すると、変更が防止されます。

2
Aoi Karasu

第一に、cv修飾参照の概念はありません。したがって、「定数参照」という用語は正しくなく、通常は「定数参照」を説明するために使用されます。何を意味しているのかを話し始めるのが良いでしょう。

$ 8.3.2/1- "Cv修飾された参照は、type-def(7.1.3)またはテンプレート型引数(14.3)を使用してcv-qualifierが導入された場合を除き、不正な形式です。修飾子は無視されます。」

ここに違いがあります

$ 13.1-「このように、パラメーター型仕様の最も外側のレベルにあるconstおよびvolatile型指定子のみが無視されます。パラメーター型仕様内に埋め込まれたconstおよびvolatile型指定子は重要であり、オーバーロードされた関数宣言を区別するために使用できます。 112)。特に、任意のタイプTについて、「Tへのポインター」、「const Tへのポインター」、および「volatile Tへのポインター」は、「Tへの参照」、「const Tへの参照」と同様に、異なるパラメータータイプと見なされます。 、および「揮発性Tへの参照」

void f(int &n){
   cout << 1; 
   n++;
}

void f(int const &n){
   cout << 2;
   //n++; // Error!, Non modifiable lvalue
}

int main(){
   int x = 2;

   f(x);        // Calls overload 1, after the call x is 3
   f(2);        // Calls overload 2
   f(2.2);      // Calls overload 2, a temporary of double is created $8.5/3
}
0
Chubsdad

最初のメソッドは、nを値で渡します。つまり、nのコピーが関数に送信されます。 2番目のものはnを参照渡しします。これは基本的に、関数が呼び出されるnへのポインターが関数に送信されることを意味します。

intのような整数型の場合、参照のサイズは通常、参照(ポインター)のサイズと同じであるため、const参照として渡すことはあまり意味がありません。コピーの作成に費用がかかる場合、通常はconst参照で渡すのが最善です。

0
Andreas Brinck