2

これを行うとき:

int square(int& x) { return x*x;};

int s = square(40); // This gives error

これを修正するには、次のようにします。

int square(const int& x) { return x*x;};

int s = square(40); // This is OK

40は定数であることを理解していますが、これを行うとどうなりますか。

const int& x = 40 

なぜそれはconstキーワードだけで大丈夫なのでしょうか?それは、誰もが参照する値を変更できないことをコンパイラが保護する方法xですか?

40はconstであるため、メモリ内の場所もわかりませんが、コンパイラはこのアドレスを認識してはなりません。したがって、コンパイラはアドレスに移動してアドレス&40を変更できるため、たとえば値を40から30に変更できます。 30までの値?

4

5 に答える 5

2

の宣言square

 int square(int& x);

は左辺値を取りますが、の呼び出しはsquare(40)右辺値を取りますが、これは一貫性がありません。左辺値と右辺値の詳細については、こちらを参照してください

于 2012-11-11T14:47:18.173 に答える
2

const参照に関する規則は、一時的な参照を非左辺値の参照にバインドすることはできないということです。リテラル40は一時的なものを初期化するために使用できますが、それ自体はオブジェクトではありません。constしたがって、非左辺値参照をそれにバインドすることはできません。

あなたがするとき

int const& value = 40;

実際には、初期化された一時オブジェクトを40参照にバインドしますvalue。通常、一時的なものは範囲外になり、完全な式の終わりに破棄されます。ただし、一時を非const参照に直接バインドすると、その有効期間は参照の有効期間と一致するように延長されます。

非参照への一時オブジェクトのバインドを禁止するルールconstは、主に多くの驚くべき結果を引き起こす可能性があるために実施されています。技術的には実行できますが、自明ではない結果が生じる可能性が非常に高くなります。

于 2012-11-11T14:49:26.193 に答える
2

実装が可能であるからといって、それを実行する必要があるとは限りません。40を実際に30にすることは陽気ですが、特に保守が不可能であり、許可されるべきではありません。さらに、40は必ずしも実際に住所を持っているわけではありません。キャッシュ、レジスタ、または即時命令の40を検討してください。

于 2012-11-11T14:44:37.750 に答える
1

定数とリテラルを混同しています。それらは似ていますが、同等ではありません。40定数ではなく、リテラルです。

リテラルを参照で渡すことはできません。参照で何かを渡す場合、それは変更できることを意味します-リテラルはできません。次のことを考慮してください。

void foo(int &i)
{
    i = 1;
}

foo(0); // What on Earth? 0 == 1?

ただし、定数への参照を渡す場合は、それが参照であっても、関数が引数を変更することを許可されていないことを意味します(定数であるため)。したがって、リテラルを安全に渡すことができます。関数が引数を変更する可能性がないので、意味があります。

于 2012-11-11T14:41:41.677 に答える
1

あなたはまだすることができます:

int x = 40;
int s = square(x)

x = 30;
s = square(x);

正方形の両方のバージョン(1つまたはconstなし)。

参照によって何かを渡すときは、既存のオブジェクトを渡します(これは、参照が既存のオブジェクトのエイリアスを意味するためです)。

あなたの例では:

int s = square(30);

オブジェクトを渡していない。これはリテラルです(オブジェクトではありません)。コンパイラは、一時オブジェクトを作成することにより、リテラルをオブジェクトに変換できます。ただし、言語には一時オブジェクトに対する明示的な制限があり、これはそれらがconstであることを意味します。これは、参照が変更されるインターフェイスに参照を渡すことができないことを意味します(ただし、const参照によって参照を渡すことはできます)。

于 2012-11-11T14:55:46.993 に答える