之前在学习C++标准库(C++11)的shared_ptr时,遇到一个成员函数owner_before,一时就懵了,后来查找相关资料,才初步了解该成员函数。
先来看看cppreference上面对于该成员函数的说明:

大概意思就是说,该成员函数用于将一个shared_ptr与另外一个shared_ptr(或者是weak_ptr)按照某种关系进行比较并返回比较结果,这种比较关系就是owner-based order。
什么是owner-based order?
这里将指针分为两种情况。一种是owner pointer,代表指针所指向的就是一个内存中的完整的对象,该对象可以被多个智能指针指向其中的某一部分;另外一种就是stored pointer,代表指针所指向的对象类型就是指针的类型,该对象可能是某个完整对象的一部分。对于这些指针,如果存在多个指针指向同一个完整对象的某一部分,则在销毁该对象时,只对完整的对象执行一次析构即可,其余的不需要进行相关析构操作了。例如:
struct A
{
int a;
double b;
};
auto pA = std::make_shared<A>();
std::shared_ptr<int> pB(pA, &pA->a);
上面的pA就是一个owner pointer,pB就是一个stored pointer。
而owner-based order的意思就是如果进行比较的两个指针指向的是同一个对象(包含继承关系),那么就认为这两个指针是“相等”的(如上述的pA和pB)。
std::shared_ptr::owner_before的功能:
用a.owner_before(b)来举例:如果a与b同为空或者同时指向同一个对象(包含继承关系),就返回false;如果是其它情况,则用指针所指向的对象的地址来比较大小,若a的地址<b的地址,则返回true,若a的地址>b的地址,则返回false。
验证代码如下:
#include <cstdlib>
#include <memory>
#include <iostream>
struct A
{
A() :a(0) {}
A(const int& aa) :a(aa) {}
int a;
};
struct B
{
B() :b(0) {}
B(const int& bb) :b(bb) {}
int b;
};
struct AB : public A, public B
{
AB() {}
AB(const int& aa, const int& bb) : A(aa), B(bb) {}
};
int main()
{
std::cout << std::boolalpha;
{
std::shared_ptr<AB> spAB(new AB(23, 45), [](AB* p) {
std::cout << "finally delete AB" << std::endl;
delete p;
});
std::shared_ptr<A> spA(spAB);
std::shared_ptr<B> spB(spAB);
std::cout << "a = " << spAB->a << ", b = " << spAB->b << std::endl;
std::cout << "AB's address: " << spAB << std::endl;
std::cout << "A's address: " << spA << std::endl;
std::cout << "B's address: " << spB << std::endl;
std::cout << "spA == spAB: " << (spA == spAB) << std::endl; // true
std::cout << "spB == spAB: " << (spB == spAB) << std::endl; // true
std::cout << "spA.owner_before(spB): " << spA.owner_before(spB) << std::endl; // false
std::cout << "spA.owner_before(spAB): " << spB.owner_before(spAB) << std::endl; // false
}
std::shared_ptr<A> a(nullptr);
auto A1 = std::make_shared<A>(90);
auto A2 = std::make_shared<A>(56);
std::cout << "A1's address: " << A1 << std::endl;
std::cout << "A2's address: " << A2 << std::endl;
std::cout << "A1.owner_before(A2): " << A1.owner_before(A2) << std::endl;
std::cout << "A2.owner_before(A1): " << A2.owner_before(A1) << std::endl;
std::cout << "A1.owner_before(a): " << A1.owner_before(a) << std::endl; // false
std::cout << "a.owner_before(A1): " << a.owner_before(A1) << std::endl; // true
system("pause");
return 0;
}