2012-09-13 87 views
3

所以,我試圖想出一個在codegolf上用C++編寫When does x==x+2的解決方案,並提出這個片段只是爲了認識到我不知道它是如何工作的。我不確定爲什麼這兩個條件評估爲真。std ::向量運算符==:值或引用比較?

有沒有人知道標記爲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(值)。我可能錯過了一些明顯的東西。提前致謝。

+1

完全沒有。 gcc 4.5.3。 –

+1

運算符'+'應該按值返回,不要改變輸入參數,像這樣:'std :: vector operator +(const std :: vector &v,int val);' – ErikEsTT

+0

我想知道標準是否允許'false '要回到這裏? – kennytm

回答

6

對於標準容器,operator==過載作爲std::equal。這反過來對itera ­ tors進行處理,並通過去聲明進行比較,如*it1 == *it2。因此,不需要副本。

表達式x == x + 2operator==(x, x + 2)相同。兩個操作數都在函數調用之前進行求值,並且由於x + 2修改了x,所以兩個操作數都是相同的。因此平等成立。

令人驚訝的是超負荷+操作員的非常規設計選擇的結果。這是在任何合作項目中集結不良做法和禁忌。如果你絕對必須超載歌劇,那麼只有當他們像預期的那樣行事,遵循既定的語義,並不奇怪。 + -operator的通用­等行爲是按值返回一個新對象,並保持操作數不受影響。像這樣:

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

回覆:糟糕的做法。可以肯定的 - 整個過程就是爲一個愚蠢的編碼難題做'x + 2 == x'。回覆:std :: equal。我對C++的瞭解越多,我就越覺得有一個''我想寫的東西。 ;)偉大的信息。謝謝。 –

+0

@NathanAndrewMullenax:我明白......這無疑是一個很好的解決方案。我可能會去一個實現模塊化算術的類:-) –

4

std::vector's equality comparison執行詞法比較,檢查lhsrhs的大小是否相同,然後逐個比較元素。

與您的代碼的問題是,你正在分配x+2y,和你的加法運算符修改lhs,像個+=運營商。

這裏:

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

這個修改x,並拷貝分配從xy。個很乖operator+會像

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

你確定嗎?據我所知,它將一個int附加到一個向量上,然後將引用返回給同一個向量。這不是這種情況嗎? –

+1

@NathanAndrewMullenax是的,完全肯定。您可以在操作員中修改'x'。 – juanchopanza

+0

@NathanAndrewMullenax:就像是說(如果'a'和'b'是'int's)'b =(a + = 2);'。最後,'a'和'b'都會有相同的結果。 – Cornstalks

1

std::vector::operator==()(通常?)功能,這是C++ 03的序列點,這意味着它需要充分評估所有的這之前它的參數可以調用。

這兩個參數都解析爲相同的參考(向量x),所以它很自然會評估爲真。

這是因爲該運算符+從不創建新的對象,它只是修改一個。

是,實際上等效於以下代碼:

std::vector<int> x; 
x.push_back(2); 
std::cout << (x==x) << "\n"; // this is no surprise 
+0

@juanchopanza我認爲itjax是說x和x + 2(而不是x和y)在作爲const運算符傳遞給==運算符之前被評估,因爲==是C++中的一個序列點。我感覺合理。 –

+0

也就是說,x + 2 == x + 4也是因爲所有的副作用都是在調用==之前評估的。 –

2

這種混淆來自+的非常規定義。通常,它會返回其參數的修改副本,而參數本身不變。由於操作者的作用更像+=,修改它的參數和返回到它的基準,這大致相當於:

x.push_back(2), x == x 

改性向量與本身。

C++總是比較值,永遠不會引用;如果您想參考比較,那麼您必須明確地比較地址&x == &y