非常长期的C ++程序员。我刚刚从Visual Studio 2010升级到Visual Studio2019。升级后,使用VS 2010编译良好的程序无法在VS 2019上编译,错误为C3848。该失败是使用std :: set发生的,与类一起使用时,需要使用operator()实现的比较功能。一个C3848错误表明我的类对象的签名与std :: set中的签名不匹配,并且不匹配是一个签名具有const,而另一个没有。
我已经有了一个非常好的解决方法,那就是在比较函数的参数列表之后添加const。我可能应该只宣布胜利并继续前进,因为我有解决方案,但该解决方案对我而言毫无意义。关于这种情况的所有文档都说,参数列表后的const适用于“ this”变量,例如,它允许两个成员方法定义,一个用于“ this”变量是常量时,而何时用于“ this”。变量不是常数。这种解释对我来说毫无意义,原因是我的小比较函数没有“ this”变量-或至少我不知道。
我的比较函数的基本结构是
class Mycomp
{
public:
bool operator() (const Myclass& x, const Myclass& y){... }
};
,如果x按顺序在y之前返回true,否则返回false。 Mycomp不引用任何类型的“ this”变量,而仅引用参数x和y。当使用诸如std :: set,std :: vector,std :: sort和C ++标准库中的许多其他服务时,此类功能非常常见,并且我编写此类代码已有近30年的历史。这是我第一次遇到这个问题。
为了完成故事,将std:set定义为
std::set<Myclass,Mycomp> the_set; // the name of the set can be
// anything, so I made be it
// be "the_set"
到目前为止,没有任何编译错误。当我尝试向集合中插入内容时,发生编译错误。
Myclass an_object; // instantiate a member of the class
// code goes here to put some data into the_object
the_set.insert(an_object); // insert the object into the set
在这种情况下,“插入”是std :: set类的成员方法,并且我的比较函数与实例化“ the_set”时称为“ the_set”的集合相关联。编译错误发生在插入操作上,而不是在比较函数的定义上发生,也没有在实例化std :: set时发生。无论如何,解决方法是将const添加到比较函数,即。
class Mycomp
{
public:
bool operator() (const Myclass& x, const Myclass& y) const {... }
};
我想这让我感到奇怪。通常,您具有确实具有“ this”变量的非静态成员方法,而您却具有不具有“ this”变量的静态成员方法。那么什么是operator()和operator <()等,是静态的还是非静态的?我从未有一个带有“ this”变量的运算符类型成员方法,但是我也从未宣布一个运算符类型成员方法是静态的。那么发生了什么?当没有“ this”变量时,为什么必须将“ this”变量声明为常量?
答案 0 :(得分:2)
我从未有一个带有“ this”变量的操作员类型成员方法,但我也从未宣布操作员类型成员方法是静态的。
您这样说,好像有两个以上的选择。如果函数是类型的成员,则它是静态的或非静态的。如果您未在成员声明/定义中写入Long.MIN_VALUE / -1
,则它具有一个static
指针。无论您是否使用它,都在那里。
在this
的活动实例上调用您的operator()
重载。因此,它以1作为指针。因此,该函数的执行与该对象之间的关系很重要。以前,Mycomp
不在乎函数是否修改了实例。但是,这样做是不确定的行为,因为允许set
创建和销毁其认为合适的实例。
C ++委员会决定不让比较运算符修改对象,而不是将其保留为无法检测到的UB。