Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::vector operator==: value or reference comparison?

Tags:

c++

vector

So, I was trying to come up with a solution for When does x==x+2 in C++ on codegolf, and came up with this snippet only to realize that I don't know how it works. I'm not sure why both of these conditions evaluate to true.

Does anyone know if the line labeled line: is true because x==&x or because x+2 is evaluated before the left-hand side of ==?

#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;
}

It seems--since vectors appear to be compared by value--that if x were evaluated before x+2, then x wouldn't be equal to x+2 (by value). I'm probably missing something obvious. Thanks in advance.

like image 351
Nathan Andrew Mullenax Avatar asked Dec 12 '22 22:12

Nathan Andrew Mullenax


2 Answers

For the standard containers, operator== is overloaded as std::equal. This in turn works on itera­tors and applies comparison by dereferncing, as in *it1 == *it2. Therefore, no copies are required.

The expression x == x + 2 is the same as operator==(x, x + 2). Both operands are evaluated before the function call, and since x + 2 modifies x, both operands are the same. Thus the equality holds.

The surprise is the result of your unconventional design choice in overloading the +-operator. This is ge­ne­rally poor practice and a taboo in any collaborative project. If you absolutely must overload opera­tors, then only if they behave as expected, follow established semantics and are not surprising. The usu­al behaviour of the +-operator is to return a new object, by value, and leave the operand unaffected. Like so:

std::vector<int> operator+(std::vector<int> v, int n)
{
    v.push_back(n);
    return v;
}
like image 173
Kerrek SB Avatar answered Feb 11 '23 03:02

Kerrek SB


std::vector's equality comparison performs a lexicographical compare that checks that the size of lhs and rhs are the same, and then compares element by element.

The problem with your code is that you are assigning x+2 to y, and your addition operator is modifying the lhs, acting like a += operator.

Here:

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

this modifies x, and copy assigns y from x. A well behaved operator+ would be something like

std::vector<int> operator+ ( std::vector<int> v, int val )
{
    v.push_back(val);
    return v;
}
like image 33
juanchopanza Avatar answered Feb 11 '23 03:02

juanchopanza