之前在學習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;
}