天天看點

淺析std::shared_ptr::owner_before

之前在學習C++标準庫(C++11)的shared_ptr時,遇到一個成員函數owner_before,一時就懵了,後來查找相關資料,才初步了解該成員函數。

先來看看cppreference上面對于該成員函數的說明:

淺析std::shared_ptr::owner_before

大概意思就是說,該成員函數用于将一個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;
}
           

繼續閱讀