文章目录
1 概述
从C++11开始C++语言越来向现代化语言转变。尤其是智能指针的引入,代码中不会直接使用new/delete了。C++11智能指针有三种分别是:shared_ptr,weak_ptr 和unique_ptr 。
2 共享指针(shared_ptr)
shared_ptr是C++11引入的,用来管理指针.其类图如下:
shared_ptr的特性:
- 可复制性,体现在拷贝构造函数和拷贝赋值函数,复制后增加引用计数use_count
- 可移动性,体现在移动构造函数和移动赋值函数。
- 可交换性,通过swap函数交换两个shared_ptr对象
- 可重置性,通过rest函数重置管理指针
- 可管理多种指针类型,既可以管理new分配指针和数组,也可以管理malloc分配指针,不过需要定制allocer和deleter。
- 相互引用性,共享指针有互相引用性问题(对象A有对象B的共享指针,对象B有对象A的共享指针),互相引用性导致对象资源无法释放,通过使用weak_ptr指针解决相互引用性
2 使用实例
void SharedPtrSuite::make()
{
std::shared_ptr<int> a = std::make_shared<int>(10);
auto b = std::make_shared<int>(20);
auto c = std::make_shared<Array>(50);
TEST_ASSERT_EQUALS(10, *a)
TEST_ASSERT_EQUALS(20, *b)
TEST_ASSERT_EQUALS(50, c->size())
}
通过重载->操作符,共享指针可以像原始指针一样使用。
3 接口使用
3.1 construct/get
获取管理的指针
void SharedPtrSuite::get()
{
std::default_delete<int> del;
std::shared_ptr<int> a;
std::shared_ptr<int> b(nullptr);
std::shared_ptr<int> c(new int(10));
std::shared_ptr<int> d(new int(10), del);
std::shared_ptr<int> e(nullptr, std::default_delete<int>());
std::shared_ptr<int> f(new int(10), [](int *p){delete p;}, std::allocator<int>());
std::shared_ptr<int> g(f);
std::shared_ptr<int> h(std::unique_ptr<int>(new int(10)));
TEST_ASSERT_EQUALS(true, a.get() == nullptr)
TEST_ASSERT_EQUALS(true, b.get() == nullptr)
TEST_ASSERT_EQUALS(true, c.get() != nullptr)
TEST_ASSERT_EQUALS(true, d.get() != nullptr)
TEST_ASSERT_EQUALS(true, e.get() == nullptr)
TEST_ASSERT_EQUALS(true, f.get() != nullptr)
TEST_ASSERT_EQUALS(true, g.get() != nullptr)
TEST_ASSERT_EQUALS(true, h.get() != nullptr)
std::shared_ptr<int> j(std::move(f));
TEST_ASSERT_EQUALS(true, f.get() == nullptr)
TEST_ASSERT_EQUALS(true, j.get() != nullptr)
}
3.2 operator bool
可以通过if条件语句判断指针是否不为空
void SharedPtrSuite::check_bool()
{
std::default_delete<int> del;
std::shared_ptr<int> a;
std::shared_ptr<int> b(nullptr);
std::shared_ptr<int> c(new int(10));
std::shared_ptr<int> d(new int(10), del);
std::shared_ptr<int> e(new int(10), std::default_delete<int>());
std::shared_ptr<int> f(std::move(d));
TEST_ASSERT_EQUALS(false, (bool)a)
TEST_ASSERT_EQUALS(false, (bool)b)
TEST_ASSERT_EQUALS(true, (bool)c)
TEST_ASSERT_EQUALS(true, (bool)c)
TEST_ASSERT_EQUALS(true, (bool)e)
TEST_ASSERT_EQUALS(true, (bool)f)
}
3.3 operator *
获取指针指向对象和变量
void SharedPtrSuite::dereference_obj()
{
std::shared_ptr<int> a(new int(10));
TEST_ASSERT_EQUALS(10, *a)
std::shared_ptr<int> b;
std::cout << "\na=" << *a << std::endl;
if(b)
std::cout << "\nb=" << *a << std::endl;
}
3.3 operator ->
该接口只有类是对象情况下使用
void SharedPtrSuite::dereference_obj_member()
{
std::shared_ptr<Array> a(new Array(10));
TEST_ASSERT_EQUALS(10, a->size())
std::cout << "\na.size=" << a->size() << std::endl;
std::shared_ptr<Array> b;
if(b)
std::cout << "\nb.size=" << b->size() << std::endl;
}
3.4 operator =
赋值操作
void SharedPtrSuite::assign()
{
std::shared_ptr<int> a(new int(10));
std::shared_ptr<int> b(new int(10));
TEST_ASSERT_EQUALS(true, (bool)a)
a = nullptr;
TEST_ASSERT_EQUALS(false, (bool)a)
a = b;
TEST_ASSERT_EQUALS(true, (bool)a)
TEST_ASSERT_EQUALS(true, (bool)b)
std::shared_ptr<int> c = std::move(b);
TEST_ASSERT_EQUALS(true, (bool)c)
TEST_ASSERT_EQUALS(false, (bool)b)
std::unique_ptr<int> d(new int(10));
TEST_ASSERT_EQUALS(true, (bool)d)
std::shared_ptr<int> f;
f = std::move(d);
TEST_ASSERT_EQUALS(false, (bool)d)
TEST_ASSERT_EQUALS(true, (bool)f)
}
3.5 reset
重置指针,delete管理的指针,并管理新传入指针(如果有的话)
void SharedPtrSuite::reset()
{
std::shared_ptr<int> a;
TEST_ASSERT_EQUALS(false, (bool)a)
a.reset();
TEST_ASSERT_EQUALS(false, (bool)a)
a.reset(new int(10));
TEST_ASSERT_EQUALS(true, (bool)a)
a.reset();
TEST_ASSERT_EQUALS(false, (bool)a)
a.reset(new int(20), std::default_delete<int>());
TEST_ASSERT_EQUALS(true, (bool)a)
TEST_ASSERT_EQUALS(20, *a)
a.reset(new int(30), std::default_delete<int>(), std::allocator<int>());
TEST_ASSERT_EQUALS(true, (bool)a)
TEST_ASSERT_EQUALS(30, *a)
}
3.6 swap
交换两个指针
void SharedPtrSuite::swap()
{
std::shared_ptr<int> a;
std::shared_ptr<int> b(new int(10));
std::shared_ptr<int> c(new int(50));
std::shared_ptr<int> d(new int(100));
TEST_ASSERT_EQUALS(false, (bool)a)
a.swap(b);
TEST_ASSERT_EQUALS(true, (bool)a)
TEST_ASSERT_EQUALS(false, (bool)b)
TEST_ASSERT_EQUALS(50, *c)
TEST_ASSERT_EQUALS(100, *d)
c.swap(d);
TEST_ASSERT_EQUALS(100, *c)
TEST_ASSERT_EQUALS(50, *d)
}
3.7 use_count
返回引用计数
struct C {int* data;};
void SharedPtrSuite::use_count()
{
std::shared_ptr<int> a(new int(10));
TEST_ASSERT_EQUALS(1, a.use_count())
std::shared_ptr<int> b = a;
TEST_ASSERT_EQUALS(2, a.use_count())
TEST_ASSERT_EQUALS(2, b.use_count())
b.reset();
TEST_ASSERT_EQUALS(1, a.use_count())
TEST_ASSERT_EQUALS(0, b.use_count())
a.reset();
TEST_ASSERT_EQUALS(0, a.use_count())
std::shared_ptr<C> c (new C);
TEST_ASSERT_EQUALS(1, c.use_count())
std::shared_ptr<int> d (c, c->data);
TEST_ASSERT_EQUALS(2, c.use_count())
TEST_ASSERT_EQUALS(2, d.use_count())
}
3.8 unique
该接口只有在类型是数组情况下使用
void SharedPtrSuite::unique()
{
std::shared_ptr<int> a(new int(10));
std::shared_ptr<int> b;
TEST_ASSERT_EQUALS(true, a.unique())
TEST_ASSERT_EQUALS(false, b.unique())
b = a;
TEST_ASSERT_EQUALS(false, a.unique())
TEST_ASSERT_EQUALS(false, b.unique())
a.reset();
TEST_ASSERT_EQUALS(true, b.unique())
}
3.9 owner_before
共享指针owner小于比较
void SharedPtrSuite::owner_before()
{
std::shared_ptr<int> a (new int (10));
std::shared_ptr<int> b (new int (10));
TEST_ASSERT_EQUALS(true, a.owner_before(b))
TEST_ASSERT_EQUALS(false, b.owner_before(a))
int * p = new int (10);
std::shared_ptr<int> c (new int (20));
std::shared_ptr<int> d (c, p); // alias constructor
//comparing c and d
TEST_ASSERT_EQUALS(true, c < d)
TEST_ASSERT_EQUALS(false, d < c)
TEST_ASSERT_EQUALS(false, c.owner_before(d))
TEST_ASSERT_EQUALS(false, d.owner_before(c))
delete p;
}
3.10 owner_less
共享指针owner小于比较函数
void SharedPtrSuite::owner_less()
{
int * p = new int (10);
std::shared_ptr<int> a (new int (20));
std::shared_ptr<int> b (a, p); // alias constructor
std::set< std::shared_ptr<int> > value_base;
std::set< std::shared_ptr<int>, std::owner_less< std::shared_ptr<int>> > owner_base;
value_base.insert(a);
value_base.insert(b);
owner_base.insert(a);
owner_base.insert(b);
TEST_ASSERT_EQUALS(2, value_base.size())
TEST_ASSERT_EQUALS(1, owner_base.size())
}
3.11 relational
void SharedPtrSuite::relational()
{
std::shared_ptr<int> a,b,c,d;
a = std::make_shared<int> (10);
b = std::make_shared<int> (10);
c = b;
TEST_ASSERT_EQUALS(false, a == b)
TEST_ASSERT_EQUALS(true, b == c)
TEST_ASSERT_EQUALS(false, c == d)
TEST_ASSERT_EQUALS(true, a != nullptr)
TEST_ASSERT_EQUALS(true, b != nullptr)
TEST_ASSERT_EQUALS(true, c != nullptr)
TEST_ASSERT_EQUALS(false, d != nullptr)
}