我已经读过std :: owner_less执行“基于所有者而不是基于值”的排序,如果两个智能指针“指向同一对象的子对象”,它们是等效的-究竟是什么意思? / p>
作为测试用例,我编写了以下代码:
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 12。在我看来,如果std :: owner_less执行“基于所有者的”比较,则不应将a和b视为相同,而默认比较器会将它们视为不同?我的代码的结果似乎是相反的。
答案 0 :(得分:4)
std::shared_ptr<T> a(t);
std::shared_ptr<T> b(t);
当shared_ptr
被销毁时,这是未定义的行为;这两个shared_ptr
不知道彼此的存在,它们将尝试删除t
。
owner_less
可以被认为是“在(真实或隐喻)控制块的地址上排序”。因此,如果它们共享所有权或都为空,则认为等效的两个shared_ptr
(和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
根据{{1}}, a
,b
和c
都是等效的,因为它们共享所有权。 owner_less
不与d
共享所有权(它具有自己的“控制块”),因此根据a
的不同。同样,对于owner_less
,它为空(什么也不拥有),但存储的指针为非null。
默认比较器仅比较存储的指针或e
。它将看到get()
,a
,b
和d
都是等效的,而e
则是不同的(假设您将双方都转换为{{1} },以便它们具有可比性。)