智能指针最佳实践
- 智能指针仅用于管理内存,不要用于管理非内存资源,非内存资源使用RAII类封装
- 用unique_ptr表达唯一所有权
- 用share_ptr表达共享所有权
- 优先采用unique_ptr而不是share_ptr,除非需要共享所有权
- 针对共享情况考虑使用引用计数
- 使用make_uniqke()创建unique_ptr
- 使用make_shared()创建shared_ptr
- 使用weak_ptr防止share_ptr的循环引用
- 原始指针(T*) 或引用(T&)没有所有权
- 以智能指针为参数,仅用于表达生存期语义,使用unique_ptr参数表达所有权转移 ,使用share_ptr参数表达不同共享所有权意图
- 如果不传递所有权,应当接受T*或T&参数而不是智能指针
- 不要把来自智能指针别名的指针或引用传递出去
- 单个表达式仅进行一次显示资源分配
注意:智能只能也不要滥用,创建指针尽量避免创建裸指针,但是使用的时候,可以使用裸指针,不要涉及所有权转移,仅仅只是使用是OK 的
智能指针推荐用法和不建议用法代码示例
#include <iostream>
#include <memory>
using namespace std;
#include <memory>
#include <iostream>
void func()
{
widget c;
//注意:如果栈对象能满足要求,就优先用栈对象,
//除非找到栈对象满足不了要求的理由才考虑使用堆对象
//堆对象 裸指针 or 智能指针? 优先智能指针(特别优先unique_ptr)
//当涉及函数传参的时候不要因为定义了unique_ptr,函数参数写成void process3(unique_ptr<widget>);
//void process1(const widget& );这种方式更推荐, void process2(widget* )这种方式也OK,但是
//都要有 “原始指针T* 或引用 T & 没有所有权,不要传递所有权给被调函数”
unique_ptr<widget> um{new widget()};
process1(*um);
process1(c);
process2(um.get());
process2(&c);//栈对象取地址要非常小心,一般不推荐
process3(std::move(um));
}
void process1(const widget& ); // 极力推荐
void process2(widget* ); //OK, 但是建议用&
void process3(unique_ptr<widget>); //较少,一般不推荐:强取豪夺所有权
void process4(share_ptr<widget>); //比unique_ptr好一点
//process5 更推荐 改为 process1(const widget& );
void process5(const unique_ptr<widget>&);
//在某些场景下比process4(share_ptr<widget>)好
//因为process4(share_ptr<widget>) 有拷贝构造,引用计数会加一而process6(const share_ptr<widget>&) 不会
void process6(const share_ptr<widget>&);
void process6_1(share_ptr<widget>&);//也有这种使用情况,当需要修改对象内容的时候
//不常见,某些场合会用上
void process7(unique_ptr<widget>& r)
{
//....
r.reset(...);
}
//改变了原始指针了,偶尔使用
void process8(share_ptr<widget>& r)
{
r.reset(...);
}
widget* process( ); // 非常不推荐!
widget& process( ); // 罕见,小心返回栈对象的引用(通常是返回参数、或者类成员对象)
unique_ptr<widget> void process(); //较为推荐,常用(大多是工厂函数)
share_ptr<widget> void process(); //OK,但不常用
unique_ptr<widget> w(new widget());
process1(*w);
process2(w.get());
unique_ptr<widget> void process1()
{
unique_ptr<widget> w{new widget()};
return w;
}
unique_ptr<widget> void process2(unique_ptr<widget>& r)
{
return r;
}
int main()
{
unique_ptr<widget> w{new widget()};
w=process1();//移动
unique_ptr<widget> w2=process1();//返回值优化
unique_ptr<widget> w3=process2(w2);//移动
}
struct Base {
virtual ~Base() { }
};
struct Derived1 : public Base {
~Derived1() { }
};
struct Derived2 : public Base {
~Derived2() { }
};
unique_ptr<Base> factory(int t) {
switch(t) {
case 1:
return std::make_unique<Derived1>();
case 2:
return std::make_unique<Derived2>();
default:
return nullptr;
}
}
int main()
{
unique_ptr<Base> u=factory(2);
shared_ptr<Base> p1 = std::move(u);
}
/*
unique_ptr<Base> p2 = factory(1);
shared_ptr<Base> s1 =move(p2);
*/