10
string foo() { return "hello"; }
int main() 
{
    //below should be illegal for binding a non-const (lvalue) reference to a rvalue
    string& tem  = foo();   

    //below should be the correct one as only const reference can be bind to rvalue(most important const)
    const string& constTem = foo();   
}
  1. GCCは、コンパイルエラーを発生させるのに適しています。std::string&一時型の型から非定数型の参照の初期化が無効です。std::string
  2. VS2008は、少なくともコンパイル警告を出すのでそれほど悪くはありません:警告C4239:使用される非標準拡張:'初期化':からstd::stringstd::string &の変換非定数参照は左辺値にのみバインドできます
  3. ここに問題のあるものがあります-VS2010(SP1)はエラーや警告なしで正常に完了します、なぜ?? !! VS2010の右辺値参照を使用して右辺値とバインドできることは知っていますが、使用していません。&&代わりに、デモコードでは、非定数左辺値参照を使用していました。

誰かがここでVS2010の動作を説明するのを手伝ってくれますか?バグですか!?ありがとう

4

4 に答える 4

12

これは、VSコンパイラの既知の問題/機能です。彼らは常にそれを許可しており、その拡張機能を削除することへのプッシュはないようです。

于 2011-08-25T11:18:07.010 に答える
9

コンパイラーは、言語拡張機能の無効化をオンにするとエラーを発行し、/W4で警告を発行します。ただし、このコードを削除すると、以前にコンパイルしたコードが破損するため、Microsoftはこれを行うことに非常に消極的です。これが、SFINAEサポートを修正しない理由でもあります。

于 2011-08-25T11:50:34.637 に答える
0

数年後のVisualStudioの多くのバージョンでは、この「拡張」がまだあり、驚きと頭痛の種を引き起こしています。はぁ...

修正は、警告C4239を単にエラーに変えることです。これにより、MSVCは、非const左辺値参照を一時的なものにバインドしようとするコードをコンパイルできなくなり、明確なコンパイラエラーが発生します。/we4239コンパイラ定義またはclコマンドライン引数に追加するだけです。

Visual Studioの場合:[プロジェクトのプロパティ]> [C / C ++]>[すべてのオプション]>[特定の警告をエラーとして扱う]>を追加4239し、他の数値はセミコロンで区切ってください。

CMakeの場合:

if(MSVC)
    add_definitions("/we4239")
endif()

これは、公式には推奨されていない、ですべての言語拡張機能を無効にするよりもはるかにうまく機能するようです。/Za私の大規模なコードベースでは、追加すると、Microsoft独自のヘッダー/Zaから1500を超えるコンパイラエラーが発生しました。winnt.h

于 2019-07-10T21:03:47.547 に答える
-1

この問題には、もっと厄介な変種があります。

class Foo {
  int _val;
public:
  Foo(int v) : _val(v) {}
  void F() { std::cout << _val << std::endl; }
};

class Bar {
  Foo& f;
public:
  Bar(Foo& f) : f(f) {}
  void F() { f.F(); }
};

int main() {
  Bar b(Foo(3));
  b.F();
}

だから:へb.fの呼び出し中に何を指しb.F()ますか?VS2013のデフォルトのデバッグ設定でコンパイルされた上記の例は、クラッシュせずに実行されて出力されますが、3もっと複雑な例ではスタックが破損する可能性があります。そうではなく、コンパイラがそれを機能させるために「賢い」ことをしている場合、私はそれが実際に行っていることはこれだと思います:

class Foo {
  int _val;
public:
  Foo(int v) : _val(v) {}
  void F() { std::cout << _val << std::endl; }
};

class Bar {
  Foo f;
public:
  Bar(Foo&& f) : f(f) {}
  void F() { f.F(); }
};

int main() {
  Bar b(Foo(3));
  b.F();
}
于 2014-08-11T01:59:34.340 に答える