所以,我试图在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(按值)。我可能错过了一些明显的东西。提前谢谢。
答案 0 :(得分:6)
对于标准容器,operator==
被重载为std::equal
。这反过来适用于迭代器,并通过解除引用进行比较,如*it1 == *it2
中所示。因此,不需要复制。
表达式x == x + 2
与operator==(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执行词典比较,检查lhs
和rhs
的大小是否相同,然后逐个元素进行比较。
您的代码存在的问题是您要将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