C++相等和等价的区别?哪些类型的容器使用相等或等价?

set中是使用自定义对象

很多人在 std::set 中使用自定义对象时,总是疑惑为啥不实现 operator== 而是实现 operator< ,这是因为这些同学没有搞懂,什么是相等,什么是等价,相等(equality)是以operator为基础,如果xy为真,则判定x和y相等。等价(equavalence)是以operator<为基础,如果!(x < y) && !(y < x)为真,则判定x和y等价。
因此,通常关联容器采用“等价”,而顺序容器采用“相等”。

在 C++ 中,std::set 是一个关联容器,它包含唯一对象的集合,这些对象按照某种排序规则排列。std::set 默认使用小于运算符 < 来比较元素,以确定它们在集合中的位置。这就是为什么你需要实现 operator< 而不是 operator== 的原因。

为什么需要实现 operator<

  1. 排序规则

    • std::set 内部使用红黑树(Red-Black Tree)来存储元素,这意味着它需要一个明确的排序规则来维持树的结构。operator< 定义了这种排序规则,确保每个元素都可以被正确地放置在其所在的位置。
  2. 唯一性检查

    • 虽然 std::set 默认不允许重复的键(即相同的元素),但它通过比较 operator< 来实现这一点。如果两个元素都不可相互小于(即 a < bb < a 都不成立),那么它们被视为相等,因此不会插入重复的元素。
  3. 效率

    • std::set 的插入和查找操作的时间复杂度为对数级 (O(log n)),这是因为它利用了红黑树的性质。为了保持这种效率,需要一个快速的方式来决定元素的相对顺序,而这正是 operator< 提供的功能。

为什么不实现 operator==

虽然 operator== 用于比较两个对象是否相等,但在 std::set 的上下文中,它并不是必需的。std::set 主要关心的是元素之间的顺序关系,而不是它们的等价关系。然而,如果你确实需要检查元素是否相等,通常会在自定义类型的类中实现 operator==,但这不是 std::set 的要求。

示例

假设我们有一个自定义类型 Person,并且我们想要基于年龄来排序 Person 对象。那么我们需要实现 < 运算符:

#include <iostream>
#include <set>

class Person {
public:
    Person(int age) : age_(age) {}
	// 关联容器中采用等价
    bool operator<(const Person& other) const {
        return age_ < other.age_;
    }

private:
    int age_;
};

int main() {
    std::set<Person> persons;
    persons.insert(Person(25));
    persons.insert(Person(30));
    persons.insert(Person(20));

    for (const auto& person : persons) {
        std::cout << "Age: " << person.age_ << std::endl;
    }

    return 0;
}

在这个例子中,std::set<Person> 会根据年龄从小到大排序 Person 对象。如果没有实现 < 运算符,std::set 将无法确定正确的排序顺序。

总结

  • std::set 使用 < 运算符来确定元素的相对顺序,这是为了维持内部排序结构(如红黑树)的性质。
  • 实现 operator< 是必要的,这样才能确保 std::set 正确地排序和去重。
  • operator== 可以用于自定义类型的其他场景,但不是 std::set 的必需条件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

andrewbytecoder

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值