首页 > 解决方案 > std::owner_less 做什么?

问题描述

我读过 std::owner_less 执行“基于所有者而不是基于值”的排序,如果两个智能指针“指向同一对象的子对象”,它们是等效的——这到底是什么意思?

作为测试用例,我编写了以下代码:

struct T {};

int main() {
    T* t = new T();

    std::shared_ptr<T> a(t);
    std::shared_ptr<T> b(t);

    std::set<std::shared_ptr<T>> set1;
    set1.insert(a);
    std::cout << set1.size() << std::endl;
    set1.insert(b);
    std::cout << set1.size() << std::endl;

    std::set<std::shared_ptr<T>, std::owner_less<std::shared_ptr<T>>> set2;
    set2.insert(a);
    std::cout << set2.size() << std::endl;
    set2.insert(b);
    std::cout << set2.size() << std::endl;
}

并且输出是 1 1 1 2。在我看来,如果 std::owner_less 执行“基于所有者”的比较,它不应该认为 a 和 b 相同,而默认比较器将它们视为不同吗?我的代码的结果似乎正好相反。

标签: c++

解决方案


std::shared_ptr<T> a(t);
std::shared_ptr<T> b(t);

shared_ptr当s 被销毁时,这是未定义的行为;两个shared_ptr不知道对方的存在,都会尝试删除t


owner_less可以被认为是“对(真实或隐喻)控制块的地址进行排序”。因此,如果它们共享所有权或都为空,则它认为等效的两个shared_ptr(and ):weak_ptr

struct T { int x, y; };

std::shared_ptr<T> a(new T{});
std::shared_ptr<T> b = a;

std::shared_ptr<int> c(a, &a->y); // aliasing constructor

std::shared_ptr<T> d(a.get(), [](T*){}); // null deleter to avoid no double delete
std::shared_ptr<T> e(std::shared_ptr<T>(), a.get()); // "non-owning" empty shared_ptr with a non-null stored pointer

a, b, 和c都是等价的,owner_less因为它们共享所有权。d不与a(它有自己的“控制块”)共享所有权,因此根据owner_less. 同样 for e,它是空的(不拥有任何东西)但有一个非空的存储指针。

默认比较器只是比较存储的指针或get(). 它将看到abde,它们都是等效c的和不同的(假设您将两边都转换为,shared_ptr<void>以便它们具有可比性)。


推荐阅读