c++ - c++ VS 2010 到 VS 2019 升级。升级后需要 const 参数列表。为什么?
问题描述
非常长期的 C++ 程序员。我刚刚从 Visual Studio 2010 升级到 Visual Studio 2019。升级后,使用 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
在这种情况下,“insert”是 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”变量声明为常量?
解决方案
我从来没有一个操作员类型的成员方法有一个“this”变量,但我也从来没有将一个操作员类型的成员方法声明为静态的。
你这么说好像有两个以上的选择。如果一个函数是一个类型的成员,那么它要么是静态的,要么是非静态的。如果你没有写static
在成员声明/定义中,那么它有一个this
指针。无论您是否使用它,它都在那里。
您的operator()
重载是在 的实时实例上调用的Mycomp
。因此,它需要一个作为指针。因此,该函数的执行与该对象之间的关系很重要。以前,set
不关心函数是否修改了实例。但是,这样做是未定义的行为,因为set
允许创建和销毁它认为合适的实例。
C++ 委员会决定简单地禁止比较运算符修改对象,而不是将此类修改保留为不可检测的 UB。
推荐阅读
- android - Resource.Id 没有找到我的按钮的定义
- python - 为什么我可以从 Azure Blob 存储读取但无法写入?
- python - 使用 OpenCV python 跟踪黄色对象
- javascript - 根据另一个数组中的值过滤数组
- javascript - 如何在管理页面中屏蔽或删除显示密码?
- python - 单元测试柯里化函数
- typescript - Typescript Union 类型允许来自两个接口的属性
- linux - 无法连接到客户机上运行的 IM 服务器
- python-3.6 - 如何将字符串类型接收到的原始字节类型数据转换为字节类型?
- c - 为什么函数指针声明需要知道参数和返回值的类型?