条款18:使用std::unique_ptr管理具备专属所有权的资源

一个非空的std::unique_ptr总是拥有其所涉到的资源;std::unique_ptr不允许复制,因为如果复制了一个std::unique_ptr,就会得到两个指涉到同一资源的std::unique_ptr;

假设我们有一个以Investment为基类的投资类型的继承体系:

class Investment {...};
class Stock: public Iverstment {...};
class Bond: public Iverstment {...};
class RealEstate: public Iverstment {...};

这种继承体系的工厂函数通常会在堆上分配一个对象并且返回一个指涉到它的指针,并当不再需要该对象时,由调用者负责删除之。Investment继承体系的工厂函数如下在:

template<typename... Ts> // 返回std::unique_ptr指涉到根据指定实参创建的对象
std::unique_ptr<Investment> makeInvestment()

调用者可以在单个作用域内像这样来使用返回的std::unique_ptr:

{
	auto pInvestment = makeInvestment(arguments);	// pInvestment的类型是std::unique_ptr<Investment>
													// *pInvestment在此析构
}

如果由makeInvestment创建的对象不应该直接删除,而是应该写入一条日志,,那么makeInvestment可以像下面一样实现:

auto delInvmt = [](Investment *pInvestment) // 一个作为自定义析构器的lambda表达式
{
	makeLogEntry(pInvestment);
    delete pInvestment;
}

template<typename... Ts> 				  // 改进的返回类型
std::unique_ptr<Investment, decltype()>
makeInvestment(Ts&&... params)
{
    std::unique_ptr<Investment, decltype(delInvmt)> pInv(nullptr, delInvmt);
    if (/*应该创建一个Stock类型的对象*/) {
        pInv.reset(new Stock(std::forward<ts>(params)...));
    }
    return pInv;
}
  • 当使用自定义析构器时,其类型必须制定为std::unique_ptr的第二个实参类型。本例中为delInmt

  • 将一个裸指针(如new运算符的结果)赋给std::unique_ptr的尝试,不会通过编译,因为这会形成裸指针到智能指针的隐式类型转换。

  • 自定义析构接受一个类型为Investment *的形参,不管在makeInvestment内实际创建的对象类型是什么,它终究会在lambda表达式中作为一个Investmnet*对象被删除。这意味着我们会通过一个基类指针来删除一个派生类对象。为此,基类Investment必须具备一个析构函数:

    class Investment {
    	public:
    	//...
    	virtual ~Investment();
    };
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值