今天我偶然发现了一件非常微妙的事情。下面是一些代码来演示:
#include <set>
#include <iostream>
class MyClass {
private:
int id = -1;
public:
MyClass() {}
MyClass(int _id) : id(_id) {}
bool operator() (const MyClass& instance1, const MyClass& instance2) const {
std::cout << id << std::endl;
std::cout << instance1.id << std::endl;
std::cout << instance2.id << std::endl;
return true;
}
};
int main(int argc, char *argv[])
{
std::set<MyClass, MyClass> classSet;
classSet.insert(MyClass(1));
classSet.insert(MyClass(2));
return 0;
}
输出是:
-1
2
1
当我使用设置 id
值的专用构造函数创建我的所有类实例时,我很惊讶 this->id
的计算结果为 -1。显然,C++ 使用标准构造函数创建了一些虚拟实例。
我的问题是:
- 是否有关于此行为的一些文档?
- 我是否违反了一些原则,例如三原则,例如复制构造函数会“修复”问题吗(复制其中一个实例,因此
this->id
为 1 或 2)?或者我是否总是必须在内部使用标准构造函数为 C++ 准备我的类?
最佳答案
当你写 std::set<MyClass, MyClass>
, 它声明类的实例 MyClass
需要用于比较集合包含的每两个实例。
如果 std::set
的比较器是默认可构造的,该集合将创建一个实例来进行比较(出于显而易见的原因)。它将使用您提供的默认构造函数,它将设置 id
到您提供的默认成员初始值设定项。
如果你要删除默认构造函数,程序将不会构建,因为 std::set
将要求您在初始化集合对象时提供一个比较器实例。
关于c++ - 容器比较器使用虚拟实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52848623/