C ++ VS 2010到VS 2019升级。升级后,在参数列表后需要const。为什么?

时间:2019-07-30 23:54:56

标签: c++

非常长期的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”变量声明为常量?

1 个答案:

答案 0 :(得分:2)

  

我从未有一个带有“ this”变量的操作员类型成员方法,但我也从未宣布操作员类型成员方法是静态的。

您这样说,好像有两个以上的选择。如果函数是类型的成员,则它是静态的或非静态的。如果您未在成员声明/定义中写入Long.MIN_VALUE / -1,则它具有一个static指针。无论您是否使用它,都在那里。

this的活动实例上调用您的operator()重载。因此,它以1作为指针。因此,该函数的执行与该对象之间的关系很重要。以前,Mycomp不在乎函数是否修改了实例。但是,这样做是不确定的行为,因为允许set创建和销毁其认为合适的实例。

C ++委员会决定不让比较运算符修改对象,而不是将其保留为无法检测到的UB。