std :: vector operator ==:值或引用比较?

时间:2012-09-13 17:09:08

标签: c++ vector

所以,我试图在codegolf上为C ++中的When does 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 个答案:

答案 0 :(得分:6)

对于标准容器,operator==被重载为std::equal。这反过来适用于迭代器,并通过解除引用进行比较,如*it1 == *it2中所示。因此,不需要复制。

表达式x == x + 2operator==(x, x + 2)相同。在函数调用之前评估两个操作数,并且由于x + 2修改x,因此两个操作数是相同的。因此,平等成立。

令人惊讶的是您在超载+ - 运算符时的非常规设计选择的结果。这通常是不良做法,也是任何协作项目中的禁忌。如果你绝对必须重载运算符,那么只有当它们按预期运行时,遵循既定的语义并且不足为奇。 + - 运算符的通常行为是按值返回一个新对象,并使操作数不受影响。像这样:

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

答案 1 :(得分:4)

std::vector's equality comparison执行词典比较,检查lhsrhs的大小是否相同,然后逐个元素进行比较。

您的代码存在的问题是您要将x+2分配给y,而您的添加运算符正在修改lhs,就像+=运算符一样。

下面:

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

这会修改x,并从y复制分配x。表现良好的operator+就像是

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

答案 2 :(得分:2)

混淆源于+的非常规定义。通常,它会返回其参数的修改副本,使参数本身保持不变。由于运算符的行为更像+=,修改其参数并返回对它的引用,这大致相当于:

x.push_back(2), x == x

将修改后的矢量与自身进行比较。

C ++总是比较值,从不引用;如果您想要参考比较,则必须明确比较地址&x == &y

答案 3 :(得分:1)

std::vector::operator==()是(通常是?)一个函数,这是C ++ 03中的一个序列点,这意味着它需要在调用之前完全评估它的所有参数。

两个参数都解析为相同的引用(向量x),因此它自然会被评估为真。

这是因为操作符+从不创建新对象,它只修改一个。

事实上,它等同于这段代码:

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