4

因此,我试图在 codegolf 上的 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的通常行为+是按值返回一个新对象,并使操作数不受影响。像这样:

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+2y,并且您的加法运算符正在修改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),因此很自然它会评估为真。

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

事实上,它等价于以下代码:

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