天天看点

浅析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;
}
           

继续阅读