4

それで、私はコードゴルフのC++でいつx== x + 2を実行するかについての解決策を考え出そうとしていましたが、このスニペットを思いついたのは、それがどのように機能するかわからないことを理解するためだけでした。これらの条件の両方が真であると評価される理由はわかりません。

line:x ==&xのため、またはx + 2が==の左側の前に評価されるため、ラベル付けされた行が真であるかどうかを誰かが知っていますか?

#include <iostream>
#include <vector>

std::vector<int>& operator+ ( std::vector<int> &v, int val )
{
    v.push_back(val);
    return v;
}

int main()
{
    std::vector<int> x;
    std::vector<int> y = x + 2; // y is a copy of x, and x is [2]

    // how are both of these are true?
    std::cout << (x==y) << "\n";    // value comparison [2]==[2]
line:
    std::cout << (x==x+2) << "\n";  // reference comparison? &x == &(x+2)

    // not sure if this is relevant
    std::cout << (x+2==x) << "\n";  // also true

    return 0;
}

ベクトルは値で比較されているように見えるので、xがx + 2の前に評価された場合、xはx + 2(値で)と等しくないようです。私はおそらく明らかな何かを見逃しています。前もって感謝します。

4

4 に答える 4

6

標準コンテナの場合、operator==は としてオーバーロードされstd::equalます。これは、反復子で機能し、参照解除による比較を適用します*it1 == *it2。したがって、コピーは必要ありません。

x == x + 2は と同じoperator==(x, x + 2)です。両方のオペランドは関数呼び出しの前に評価され、x + 2modifiesであるためx、両方のオペランドは同じです。したがって、等式が成立します。

+驚きは、 -operatorのオーバーロードにおける型にはまらない設計の選択の結果です。これは一般的に悪い習慣であり、共同プロジェクトではタブーです。絶対に演算子をオーバーロードする必要がある場合は、演算子が期待どおりに動作し、確立されたセマンティクスに従っている場合にのみ、驚くべきことではありません。+-operatorの通常の動作は、値によって新しいオブジェクトを返し、オペランドは影響を受けないままにすることです。そのようです:

std::vector<int> operator+(std::vector<int> v, int n)
{
    v.push_back(n);
    return v;
}
于 2012-09-13T17:19:50.257 に答える
4

std::vector の等値比較lhsは、とのサイズが同じであることを確認する辞書式比較を実行し、rhs要素ごとに比較します。

コードの問題は、 に代入x+2していyて、加算演算子が を変更していて、演算子lhsのように振る舞っていること+=です。

ここ:

std::vector<int> y = x + 2;

これは を変更し、からx割り当てをコピーします。行儀の良いものは次のようになりますyxoperator+

std::vector<int> operator+ ( std::vector<int> v, int val )
{
    v.push_back(val);
    return v;
}
于 2012-09-13T17:16:25.903 に答える
2

混乱は、の型破りな定義から生じ+ます。通常、引数自体は変更せずに、引数の変更されたコピーを返します。演算子は+=、引数を変更してその引数への参照を返すように動作するため、これはおおよそ次のようになります。

x.push_back(2), x == x

変更されたベクトルをそれ自体と比較します。

C ++は常に値を比較し、参照はしません。参照比較が必要な場合は、アドレスを明示的に比較する必要があります&x == &y

于 2012-09-13T17:21:29.180 に答える
1

std::vector::operator==()は (通常?) 関数であり、これは C++03 のシーケンス ポイントです。つまり、呼び出す前にすべてのパラメーターを完全に評価する必要があります。

どちらのパラメーターも同じ参照 (ベクトル x) に解決されるため、true と評価されるのは自然なことです。

これは、その operator+ が新しいオブジェクトを作成することはなく、オブジェクトを変更するだけだからです。

実際、これは次のコードと同等です。

std::vector<int> x;
x.push_back(2);
std::cout << (x==x) << "\n"; // this is no surprise
于 2012-09-13T17:17:18.973 に答える