C++ 为什么可以';t this std::find compare这些对象

C++ 为什么可以';t this std::find compare这些对象,c++,c++11,std,C++,C++11,Std,通常,当我执行std::find时,我会将谓词作为第三个参数,但这次我想我会做得不同,我不明白为什么它不起作用 #include <iostream> #include <vector> #include <algorithm> struct RenderJob { RenderJob() {}; int renderJob_ID; bool operator==(RenderJob& rhs) { return rhs.re

通常,当我执行std::find时,我会将谓词作为第三个参数,但这次我想我会做得不同,我不明白为什么它不起作用

#include <iostream>
#include <vector>
#include <algorithm>

struct RenderJob
{
    RenderJob() {};
    int renderJob_ID;
    bool operator==(RenderJob& rhs) { return rhs.renderJob_ID == this->renderJob_ID; }
};

int main()
{
    RenderJob foo;
    RenderJob foo2;
    foo == foo2; // Works

    std::vector<RenderJob> renderJobs;

    std::find(renderJobs.begin(), renderJobs.end(), foo); // Doesn't work
}
如果情况正好相反:

foo2 == *pToRenderJob; // This would fail because the 
                        // operator==(RenderJob&) the actual argument 
                        // is not const. Very subtle rules

您关闭了
const
限定符

bool operator==(const RenderJob& rhs) const { ... }

在我看来,这是一个常量正确性问题。请尝试以下方法:

bool operator==(RenderJob const &rhs) const { 
    return rhs.renderJob_ID == this->renderJob_ID; 
}
你自己做比较是有效的,因为你只是传递了一些简单的对象,这些对象不是临时对象,也不是常量。使用
std::find
,比较函数将(至少通常)接收对集合中对象的引用(通常是常量限定的),因此它需要能够接收常量限定的引用

但这仍然没有意义,在上面的示例中,右侧是
foo2
,它不是常量,应该指向非
常量
运算符==
。除非有一条一般规则规定,
const
和非
const
不能进行比较

语言中没有规则规定不能比较
const
和非
const
对象。您必须确保可以使用适当的
const
限定符对它们进行比较

线路

*pToRenderJob == foo2;
相当于

pToRenderJob->operator==(foo2);
foo2.operator==(*pToRenderJob)
这不起作用,因为不能使用
pToRenderJob
调用非
const
成员函数<代码>foo2
不是这里的问题

如果你使用

foo2 == *pToRenderJob
相当于

pToRenderJob->operator==(foo2);
foo2.operator==(*pToRenderJob)
这也是一个问题,因为函数的参数是
const
对象,而函数需要非
const
引用。同样地,
foo2
不是问题所在


将函数设为
const
成员函数并将参数设为
const
引用可确保操作符两侧的
const
和非
const
对象的所有组合都可以毫无问题地使用。

哦,我明白了,它起作用了。但是,我自己能够比较它们。std::find中的compare函数不是只使用操作符==函数吗?@Zebrafish
find
通过常量引用获取要比较的值。是的,谢谢。特别是const RenderJob,而不是函数后面的一个。但是我不明白,我可以自己比较它们,因为操作符==重载,std::find不是只使用操作符==函数吗?两者都应该是常量。当编译器正在查找const数据上的运算符时,它将拒绝考虑不保证const行为的运算符。现在我理解了,但是,在我的另一个例子中,右边是非const的,因此我认为应该调用非const运算符==,当然,除非在比较常量和非常量时通常存在问题。非常量对象可以升级为常量对象。记住,const只是意味着一个对象被标记为“不允许修改它”,不管对象的实际可修改性如何。在您的示例中,您不能执行
*const==foo2
*pToRenderJob==foo2
,因为
运算符==
未声明允许
常量
左操作数变为
*this
。如果该类有一个函数
void f(),则情况也是如此-您无法执行
constit->f()
pToRenderJob->f()
。但是如果您将该函数更改为
void f()const,这两个都可以。谢谢,许多规则正在慢慢设置。您还应该在类中定义
renderJob\u ID
int renderJob\u ID{}
。保留未初始化的对象是过早的优化。在您的示例中,foo.renderJob_ID和foo.renderJob_ID具有不确定值,如果您声明
std::vector renderJobs(10)
以创建一个10的向量
renderJobs
,那么这10个对象的renderJob_ID都将具有不确定值。因此,即使在将const添加到operator==参数之后,您的代码也将继续不起作用。这非常有趣,因此在我创建实际函数const时起作用的*pToRenderJob==foo2中。“非常有趣,也很微妙的规则。”斑马鱼。习惯这些规则需要一段时间,但更重要的是,随着对语言理解的加深,这些规则开始变得有意义。