使用C++,最重要的一块技能就是内存的分配和管理。这也是C/C++ 中陷阱最多的地方。说来惭愧,我曾经写过一个获取网卡信息的接口,有一个返回分支没有调用free函数释放资源,运行时间常了之后,进程占用的内存越来越大。后来自己总结,要避免这种错误的发生,一个是自身要检查好代码,可以使用其他辅助工具如 静态代码检查工具CppCheck 和 内存泄漏valgrid等。
对于JAVA开发,就不必花那么多精力去关心内存问题。C++ 在这块的改进最明显的就是引入了智能指针,不必再担心是否忘记释放内存。一些搞跨平台开发的项目对这个可能要求不高,因为工程可能要兼容很多平台,有些平台的C++运行环境未必支持指针,但这毕竟不是主流,智能指针还是要了解一下的。
我曾经写过一个函数追踪的类,大概功能是,在要追踪的函数里面声明一个追踪类对象,然后把函数名 __ FUNC_NAME __ 作为初始化参数传递进去。这个tracer类,内部只实现构造和析构。因为函数开始的时候,对象开始构造,函数结束之前销毁对象。在构造函数中,打印一句func_name 开始了,析构函数中打印一句, func_name结束了。这里面的一个原理,是栈变量离开作用域时,会自动销毁。智能指针本质上是一个对象,它重载了*和->运算符,在行为上和普通指针的使用相同。为了兼容不同类型,里面用到了模板技术。
STL提供的智能指针有四种,auto_ptr, unique_ptr, share_ptr, weak_ptr, 了解了他们之间的关系就很容易记住和使用。使用这四个指针,需要引入头文件
#include <memory>
using namespace std;
- auto_ptr实现了智能指针的基本功能,但是当右值时,会被剥夺资源,再次访问时,易出错。现在C++11,已明确废弃,不提倡使用了。
auto_ptr<int> a1(new int(1));
auto_ptr<int> a2 = a1;
// get函数返回真正的指针
if(a1.get() == NULL)
cout << "a1 is null"<<endl;
else
cout<<*a1<<endl;
if(a2.get() == NULL)
cout << "a2 is null"<<endl;
else
cout<<*a2<<endl;
- unique_ptr 是解决了auto_ptr的问题,它不允许赋值给其他智能指针. unique_ptr独占资源所有权,离开作用域时,释放资源。
unique_ptr<int> u1(new int(5));
//unique_ptr<int> u2 = u1; //error
//unique_ptr<int> u3(u1); //error
cout<<*u1<<endl;
auto us = make_unique<Simple>();// C++ 14
- shared_ptr 用来解决共享资源的情况,它内部采用了引用计数。
shared_ptr<int> s1(new int(6));
shared_ptr<int> s2 = s1;
shared_ptr<int> s3(s1);
cout<<*s1<<endl;
cout<<*s2<<endl;
cout<<*s3<<endl;
cout<<s1.use_count()<<endl;//返回引用计数数量
- weak_ptr的引入是为了解决shared_ptr中两个或以上类相互包含,造成死锁,无法使引用计数归零的情况。weak_ptr并不会使引用数量增加。注意,weak_ptr不能直接调用成员函数,要使用lock() 返回一个shared_ptr智能指针,然后才可以调用成员函数。
class SampleB;
class SampleA
{
public:
shared_ptr<SampleB> psb;
void echo()
{
cout<<"I am SampleA"<<endl;
}
~SampleA()
{
cout<<"~SampleA" << endl;
}
};
class SampleB
{
public:
//shared_ptr<SampleA> psa;
weak_ptr<SampleA> psa;
~SampleB()
{
cout<<"~SampleB" << endl;
}
};
int main()
{
shared_ptr<SampleB> pb(new SampleB());
shared_ptr<SampleA> pa(new SampleA());
pb->psa = pa;
pa->psb = pb;
cout<<pb.use_count()<<endl;
cout<<pa.use_count()<<endl;
pb->psa.lock()->echo();
return 0;
}
上面就是C++提供四个智能指针, 使用起来和普通指针相似,很容易上手。
auto_ptr,C++11 已废弃
shared_ptr,unique_ptr,weak_ptr C++11加入
make_unique C++14