7

私は Visual Studio Express 2013 を使用しており、C++ でさまざまなことを学ぼうとして少し浮気しています。

コンパイラで、参照と同じ型に明示的に型キャストしたときに一時オブジェクトが作成されないように見える興味深いバグを見つけました。

#include <iostream>

using namespace std;

int main()
{
    int number; // float number;
    number = 2;

    const int& plainref_i = number;
    const int& recastref_i = (int)number; // this goes wrong if number is int
    const float& plainref_f = number;
    const float& recastref_f = (float)number; // this goes wrong if number is float

    number = 3;

    std::cout << plainref_i << "\n";
    std::cout << recastref_i << "\n";
    std::cout << plainref_f << "\n";
    std::cout << recastref_f << "\n";

    return 0;
}

これを VS でコンパイルすると、次の出力が得られます: 3 3 2 2

ただし、gcc でコンパイルすると、次の出力が得られます: 3 2 2 2

「int number;」を置き換えると 「浮動小数点数;」VSに入る: 2 2 3 3

そしてgccの場合:2 2 3 2

誰かがこれをバグとして確認できるかどうか、また実行可能な回避策/解決策を誰かが知っているかどうか疑問に思っています。

4

1 に答える 1

3

与えられた:

 int number;

このキャストの結果は、prvalue である必要があります。

const int& recastref_i = (int)number; // this goes wrong if number is int

const 参照を使用しているため、prvalue にバインドでき、その値は変更から切り離す必要がありますがnumber、Visual Studio にはprvalue の代わりに左辺値を生成する拡張機能があるため、実際には左辺値参照を受け取りますnumber。の値numberを確認すると、への値の変更が反映されますrecastref_i

Visual Studio チームは、/Zc:rvalueCastフラグを使用してこの動作をオフにすることをお勧めします (強調鉱山)。

/Zc:rvalueCast オプションが指定されている場合、コンパイラは C++11 標準に従って、キャスト操作の結果として右辺値参照型を正しく識別します。オプションが指定されていない場合、コンパイラの動作は Visual Studio 2012 と同じです。既定では、/Zc:rvalueCast はオフになっています。適合性を確保し、キャストの使用におけるエラーを排除するために、/Zc:rvalueCast を使用することをお勧めします。

実際のシナリオで問題/Zaになる可能性のあるすべての拡張機能を無効にするものとは対照的です。

ドラフト C++ 標準セクション5.4 Explicit type conversion (cast notation)パラグラフ1から (強調鉱山):

式 (T) cast-expression の結果は T 型です。T が左辺値参照型または関数型への右辺値参照である場合、結果は左辺値であり、T がオブジェクト型への右辺値参照である場合は xvalue です。それ以外の場合、結果は prvalue です。

于 2015-02-09T03:45:59.113 に答える