c++ - 容器比较器使用虚拟实例

标签 c++ std

今天我偶然发现了一件非常微妙的事情。下面是一些代码来演示:

#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/

相关文章:

c++ - 如何覆盖 boost::geometry::equals 算法中的浮点公差?

c++ - 获取插入 vector 中的对象的索引

c++ - 在可移动类的构造函数中初始化 std::thread

c++ - 加速 C++ 代码

c++ - 将命令行从一个exe发送到另一个exe

c++ - 自制范围锁不锁定

c++ - 模板化 std::future 返回问题

C++。如何比较 2 个对象 vector

c++ - 是否可以将 mex 代码转换为 C++ 代码?

c++ - vector 构造函数/析构函数调用