您的位置:首页 > 编程语言 > C语言/C++

C++智能指针测试

2016-04-13 10:40 281 查看
<pre class="cpp" name="code"><pre class="cpp" name="code">#include <iostream>
#include <memory>
#include <assert.h>
using namespace std;

int main(int argc, char* argv[])
{
int *p1 = new int(10);
int *p2 = new int(10);
p2 = p1;
std::shared_ptr<int> sp(new int(10));//一个指向整数的shared_ptr
//	std::shared_ptr<int> sp(p1);
//	std::shared_ptr<int> sp = make_shared<int>(10);

//	assert(sp.unique());//现在shared_ptr 是指针的唯一持有者

std::shared_ptr<int> sp2(p2);//第二个shared_ptr ,拷贝构造函数
//	std::shared_ptr<int> sp2(p1);//第二个shared_ptr ,拷贝构造函数
//	std::shared_ptr<int> sp2(sp.get());

std::shared_ptr<int> sp3(sp2);

//两个shared_ptr 相等,指向同一个对象,且引用计数为2
std::cout << sp.use_count() << std::endl;
std::cout << sp2.use_count() << std::endl;
std::cout << sp.unique() << std::endl;
std::cout << (sp == sp2) << std::endl;
std::cout << (*sp == *sp2) << std::endl;

*sp2 = 50;
std::cout << *sp << std::endl;

//assert(sp == sp2 );//&& sp.use_count() == 1 && sp2.use_count() == 1

*sp2 = 100;//使用解引用操作符修改被指对象
assert(*sp2 == 100);//另一个shared_ptr 同时也被修改

sp.reset();
assert(!sp);//sp 不再持有对象
return 0;
}




经测试可以看出,一个普通的指针p1只能初始化一个智能指针shared_ptr   sp,如果还想要一个智能指针sp2指向p1,必须一定要用sp来初始化sp2。

如果也用p1初始化sp2,则sp与sp2的引用计数都只有1,而且可以测试出引用计数是不唯一的。不过sp==sp2竟然值为1。

测试完毕后可以大致判断出智能指针的运行机制如下。

一个智能指针若是使用普通指针进行初始化,则会创建一个控制器,控制器里会记录该普通指针(即指向的内存位置)和引用计数,引用计数置为1

若同一个普通指针(也可以是指向同样内存的2个普通指针)对2个智能指针进行初始化。 则会创建2个控制器,2个控制器会是独立的,引用计数均为1。而且后面会出现重复析构,所以需避免该用法。 

sp.unique()的判断依据应该是引用计数是否为1。

而且这2个智能指针竟然sp==sp2,也就是说相等符号的判断依据应该是 判断控制器里的普通指针(即指向的内存位置)是否相同, 而不是判断控制器是否相等,也不是判断引用计数是否相等。   //   这里也可以看出,智能指针尽量模仿指针的用法,想想这样做还是很合理的。

同样,判断2个智能指针的值是否相等*sp==*sp2,   类似普通指针,判断依据 只考虑值是否相等, (即使指向的内存位置不同,但只要值相等即可,就判断相等)。

上面是通过测试来估计运行机制,来更深刻的记住智能指针的方法,这样对于一些不规范的代码进行分析,当然不规范就要改成规范。

总而言之,以后使用智能指针,应避免出现普通指针,也就是是说应按照如下规范

// Use make_shared function when possible.
auto sp1 = make_shared<Song>(L"The Beatles", L"Im Happy Just to Dance With You");

// Ok, but slightly less efficient.
// Note: Using new expression as constructor argument
// creates no named variable for other code to access.

shared_ptr<Song> sp2(new Song(L"Lady Gaga", L"Just Dance"));         //尽量少用这个方法,这样也更加美观,效率也不错

// When initialization must be separate from declaration, e.g. class members,
// initialize with nullptr to make your programming intent explicit.

shared_ptr<Song> sp5(nullptr);
//Equivalent to: shared_ptr<Song> sp5;
//...

sp5 = make_shared<Song>(L"Elton John", L"I'm Still Standing");

//Initialize with copy constructor. Increments ref count.
auto sp3(sp2);

//Initialize via assignment. Increments ref count.
auto sp4 = sp2;

//Initialize with nullptr. sp7 is empty.

shared_ptr<Song> sp7(nullptr);

学习笔记:shared_ptr陷阱  
http://blog.csdn.net/liuzhi1218/article/details/6993554 https://msdn.microsoft.com/zh-cn/library/hh279674.aspx http://mingxinglai.com/cn/2013/01/smart-ptr/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: