2

私はこの構文構造に数回出くわしました、そして私は疑問に思っています:

  1. これは何をしますか?
  2. デザインの理由は何でしょうか?

次のようになりがちです。

struct SubType : public SomeSuperType {

    SubType(int somthing) : SuperType(something), m_foo(*((FooType *)0))
    {}

    private:
    FooType m_foo;
}

明確にするために、コードは機能します。しかし、目的は何ですか?その行がない場合のステータスはどうなりますm_fooか?

4

3 に答える 3

6

このコンストラクトの目的は、SomeType正式にはオブジェクトが必要であるが、実際のオブジェクトを宣言したくない、または宣言できない場合に、タイプの名前のない偽のオブジェクトをエミュレートすることです。有効な用途があり、必ずしも未定義の動作を引き起こすわけではありません。

古典的な例は、クラスメンバーのサイズを決定することです

sizeof (*(SomeClass *) 0).some_member

または decltype の同様のアプリケーション

decltype((*(SomeClass *) 0).some_member)

上記の例のいずれも、未定義の動作を引き起こしません。評価されていないコンテキストでは、のような表現*(SomeClass *) 0は完全に合法で有効です。

この手法は、8.3.5/12 のように、言語標準自体で説明目的で使用されていることも確認できます。

後続の戻り型は、declarator-id の前に指定するのがより複雑な型に最も役立ちます。

template <class T, class U> auto add(T t, U u) -> decltype(t + u); 

それよりも

template <class T, class U> decltype((*(T*)0) + (*(U*)0)) add(T t, U u);

型との間の二項演算子の結果型のコンパイル時予測を実行するために(*(T*)0) + (*(U*)0)式がどのように使用されるかを観察します。decltype+TU

もちろん、繰り返しになりますが、そのようなトリックは、上記のように、評価されていないコンテキストで使用された場合にのみ有効です。

次のように、「null 参照」の初期化子として使用されることがあります。

SomeType &r = *(SomeType *) 0;

しかし、これは実際には何が合法であるかの境界を越えており、未定義の動作を引き起こします。

評価されたコンテキストで無効な「null lvalue」にアクセスしようとするため、特定の例にあるものは無効です。

&PS C言語には、演算子と*相互にキャンセルするという仕様の特有の部分もあります。つまり、それ&*(SomeType *) 0は有効で、nullポインターに評価されることが保証されています。ただし、C++ には拡張されません。

于 2012-12-07T16:28:49.443 に答える
5

これは何をしますか?未定義の動作。

デザインの理由は何でしょうか?未定義の動作を引き起こしたいという願望。他に理由はありません。

于 2012-12-07T16:03:13.017 に答える
1

例は必ずしもUBではないと思います。の定義によりFooTypeます。何かを行うコンストラクターFooを持つ空のクラスであるとします。

class Foo {
  public:
    Foo() { std::cout << "Hey, world! A new Foo just arrived.\n"; }
    // I think the default copy and assign constructors do nothing
    // with an empty type, but just in case:
    Foo(const Foo&) {}
    Foo& operator=(const Foo&) { return *this; }
};

さて、何らかの理由で Foo が必要で、コンストラクターをトリガーしたくないとします。operator* は逆参照せず、コピー コンストラクターはその参照引数を使用しないため、これを行っても実際の逆参照は発生しません。

Foo(*static_cast<Foo*>(0));
于 2012-12-07T20:11:56.757 に答える