2012-02-02 8 views
17

今朝私がBOOST_STATIC_ASSERTを使用して間違ったタイプの参照を作成していないことを確認するためにテンプレートコードを作成していました。C++はどのようにconst doubleを処理しますか?&はintを参照していますか?

#include <iostream> 

int main() 
{ 
    int x = 5; 
    const double& y = x; 
    std::cout << y << std::endl; 

    return 0; 
} 

:私は、私はあなたがconstのダブル&がintに言及作るしようとしたときにも文句を言わないのgccを発見するためにショックを受けた代替コンパイラエラーを見てみることを静的アサートを削除しようとしたがときコンパイルしても警告しません:

$ g++ ~/stuff/badRef.cpp -Wall -Wextra -pedantic 
$ a.out 
5 

ここでは何が起こっていますか?これは未定義の動作ですか?もしそうなら、なぜgccは文句を言わないのですか?私のマシンでは、intは4バイト、doubleは8です。つまり、doubleを印刷すると、そのアドレスの8バイトをdoubleと解釈して出力するはずですが、実際にはその位置に4バイトのintがあります。

非常に混乱しています。助けて!

+0

GCCのどのバージョンですか? –

+0

バージョン4.3.3です。 – voltrevo

+0

'const double&y = x;'の後に 'x = 42;'を追加するとどうなりますか?一見すると不思議に思われるかもしれません。 – moala

答えて

22

const double& y = x;は、値static_cast<double>(x)の一時的なdoubleを作成し、その一時的な値をyにバインドします。一時的なライフタイムは、寿命がyになるように延長されます。

これは完全に合法的なC++(03と11)なので、警告/エラーがありません。

+0

素晴らしい。あなたがxをインクリメントしてからyをプリントするときに何が起こるかを見て、答えの直前に実際に分かりました。それは変わっていないので、私は思った - "もちろん、それは一時的なものに結びつく!"また、gccは-std = C++ 98でもそれを受け入れますので、有効なC++ 98でもありますか? – voltrevo

+0

@ Mozza314: "*有効なC++ 98でもあると思いますか?*"はい。私はその特定の標準のコピーを手元に持っていませんが、C++ 03で追加されたものの1つではありません。しかし、 '-std = C++ 98'は実際にC++ 98のルールではなくC++ 03のルールを強制し、引数名は耐えられないことに注意してください。 – ildjarn

+0

私はそれを得ることはできません...なぜあなたは 'const double'の代わりに一時的にバインドするときに' const double& 'をやるでしょうか? – Mehrdad

2

const T&は一時的にバインドできるため、doubleに変換され、コピーはyにバインドされています。チェックすると、&x != &yが表示されます。この動作の理由は、リテラルをconst参照でパラメータをとる関数に渡すことができるようにするためです。

+0

まあ、 "コピーが保存されていません"、yはコンスタント左辺参照なので変換結果の一時的なものにバインドします。 –

+0

@CatPlusPlus: "格納されている"に "置き換えられた"と置き換えられました。明確にならない場合は、少なくともpedanticallyな修正が必要です。 :P –

11

十分に定義されており、合法です。 yは一時的なものを指します。また、参照がをCONSTされていない場合、これは有効なC++ ではないこと

void foo(const int& p); 
foo(3.14); 

注:パラメータを渡すときにも考慮する。 VS 6は間違っていて、一時的な参照をバインドすることを許可しました。これはconst参照にのみ適用されます。

1

これはポインタと参照が同じだと思う人のための良い例です。

double const*const y2 = &x; 

gives 
bad.cpp:7:30: error: cannot convert ‘int*’ to ‘const double* const’ in initialization 

参考になる理由は、他の記事で説明されています。

関連する問題