8

myint++++ が VS2008 コンパイラと gcc 3.42 コンパイラで正常にコンパイルされるのはなぜですか?? 私は、コンパイラが左辺値が必要だと言うことを期待していました。例は以下を参照してください。

struct MyInt
{
    MyInt(int i):m_i(i){}

    MyInt& operator++() //return reference,  return a lvalue
    {
        m_i += 1;
        return *this;
    }

    //operator++ need it's operand to be a modifiable lvalue
    MyInt operator++(int)//return a copy,  return a rvalue
    {
        MyInt tem(*this);
        ++(*this);
        return tem;
    }

    int     m_i;
};

int main()
{
    //control: the buildin type int
    int i(0);
    ++++i;  //compile ok
    //i++++; //compile error :'++' needs l-value, this is expected

    //compare 
    MyInt  myint(1);
    ++++myint;//compile ok
    myint++++;//expecting compiler say need lvalue , but compiled fine !? why ??
}
4

6 に答える 6

8

いいえ、オーバーロードされた演算子は演算子ではなく、関数です。したがって、GCCはそれを受け入れるのが正しいです。

myobj++++;クラス型の一時オブジェクトでメンバー関数myobj.operator++(0).operator++(0); (オーバーロードされた演算子を含む) を呼び出すことは許可されています。

于 2011-07-14T10:53:53.880 に答える
3

ユーザー定義型の場合、演算子のオーバーロードは文字通り単なる関数呼び出しであるため、関数呼び出しのセマンティクスに従います。

于 2011-07-14T10:54:37.580 に答える
2

組み込みの動作をエミュレートしたい場合は、実際には非常に簡単な解決策があります。戻り値を作成しますconst

MyInt const operator++(int) { … }

数年前、ユーザー定義の演算子が組み込みの動作を正確にモデル化する必要があるかどうかについて議論がありました。現在、どちらの学派が優位に立っているかはわかりませんが、戻り値の型をoperator++(int) constにすることは、これを達成する方法でした。

于 2011-07-14T15:03:38.917 に答える
1

最後に、MyInt::operator++(int)別の方法です。同じルールが適用されます。右辺値でメソッドを呼び出すことができるので、右辺値で呼び出すことができますoperator++(int)

于 2011-07-14T10:56:47.623 に答える
1

myint++ は MyInt(2) に似たものを返します。つまり、MyInt(2)++ を実行するのと似ています。operator++ 関数で一時クラスが作成され、一時クラスをインクリメントしています。返された後、次のステートメントが終了するとすぐに削除されます (ここでは、2 番目の ++ 演算子です)。

于 2011-07-14T11:00:26.737 に答える
1

問題は、整数型とユーザー定義型のポストインクリメント演算子の要件が異なることです。特に、メンバー関数として実装されたユーザー定義のポストインクリメント演算子では、右辺値を使用できます。

演算子をフリー関数として実装した場合:

MyInt operator++(MyInt [const][&] x, int)

次に、その特定のオペレーターの要件は、実際の署名から抽出されたものになります。最初の引数が値で取得される場合は、右辺値を直接受け入れます。それまでに引数const &を取得する場合は、コピー コンストラクターにアクセスできる場合は右辺値を受け入れます。引数が非定数で取得される場合、&その演算子は左辺値を必要とします。

于 2011-07-14T11:27:40.753 に答える