为什么需要空shared_ptr以及如何使用它

Why does one need a null shared_ptr and how can it be used?

本文关键字:何使用 ptr shared 为什么      更新时间:2023-10-16

在Scott Meyers的Effective c++ , item 18 使接口易于正确使用而不易错误使用中,他提到了null shared_ptr:

std::tr1::shared_ptr<Investment> pInv(static_cast<Investment*>(0), getRidOfInvestment)

和vogue赋值操作

pInv = ...     //make retVal point to the correct object

在这种情况下,可能需要创建一个空shared_ptr并在稍后进行赋值?为什么不只要有资源(原始指针)就创建shared_ptr呢?

由于Scott Meyers在前面的示例中没有显示完整的赋值操作,我认为shared_ptr的赋值操作符是重载的,可以这样做:

pInv = new Investment;    // pInv will take charge of the pointer
                          // but meanwhile keep the delete function it already had

但是我尝试了boost的实现,它不这样工作。那么shared_ptr为空有什么意义呢?

我几乎可以肯定我在这里遗漏了一些东西,谁来帮帮我吧。

p。关于shared_ptr

的初始化和赋值的更多信息
#include <boost/shared_ptr.hpp>
int main(int argc, char *argv[])
{
    boost::shared_ptr<int> ptr1(new int);
    boost::shared_ptr<int> ptr2;
    ptr2.reset(new int);
    boost::shared_ptr<int> ptr3 = new int;
    return 0;
}

这个例子不能被g++编译(Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2和最新的boost:

sptr.cpp: In function ‘int main(int, char**)’:
sptr.cpp:8:39: error: conversion from ‘int*’ to non-scalar type ‘boost::shared_ptr<int>’    requested

不需要使用该hack来获得null(空)shared_ptr。只需使用默认构造函数:

std::shared_ptr<Investment> pInv; // starts null

将指针赋值给shared_ptr,可以在构造时执行:

std::shared_ptr<Investment> pInt(new Investment);
// not allowed due to explicit annotation on constructor:
// std::shared_ptr<Investment> pInt = new Investment;

或者使用.reset()函数:

pInt.reset(new Investment);

那篇文章的作者可能打算提供一个自定义删除器(getRidOfInvestment)。然而,当.reset()被调用时,或者当内部指针被改变时,deleter函数被重置。如果你想要一个自定义的删除器,你必须在shared_ptr创建的时候把它传递给.reset()

您可能想使用的一种模式是自定义创建函数,以使此操作更简单:
class Investment {
protected:
  Investment();
  // ...
public:
  static shared_ptr<Investment> create();
};
shared_ptr<Investment> Investment::create() {
  return shared_ptr<Investment>(new Investment, getRidOfInvestment);
}

后:

shared_ptr<Investment> pInv = Investment::create();

这将确保您始终将正确的析构函数附加到从 Investments创建的 shared_ptrs上。

这是相同的原因有一个空的原始指针-例如

说你有:

typedef std::tr1::shared_ptr<Investment> InvestmentPtr;
map<key,InvestmentPtr> portfolio;
...
get(mykey) {
  iterator it = portfolio.find(mykey);
  if (it == portfolio.end()) 
    return InvestmentPtr();
  else 
    return it->second;
  }
}

这允许你做:

InvestmentPtr p = get(key);
if (p) ...

让对象默认为可构造的原因有很多。首先,您希望智能指针尽可能与原始指针相似,并且由于您可以说int * p;(并获得未定义,未初始化的指针),您也可以说shared_ptr<int> p;并获得不指向任何地方的指针(但您可以使用!进行测试)。

最令人信服的原因之一可能是您可以使用shared_ptr s创建容器,并且您可以填充容器而无需立即分配指针。