C++ 为什么需要一个空的 shared_ptr 以及如何使用它?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6866146/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 20:47:12  来源:igfitidea点击:

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

c++c++11shared-ptreffective-c++

提问by zhanwu

In Scott Meyers's Effective C++, item 18 Make interfaces easy to use correctly and hard to use incorrectly, he mentioned the null shared_ptr:

在 Scott Meyers 的Effective C++ 中,第 18 项使接口易于正确使用和难以错误使用,他提到了 null shared_ptr:

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

and a vogue assignment operation

和一个时髦的赋值操作

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

In which case one may need to create a null shared_ptr and do assignment later? Why not just create the shared_ptr whenever you have the resources (raw pointer)?

在哪种情况下,可能需要创建一个空的 shared_ptr 并稍后进行分配?为什么不在拥有资源(原始指针)时创建 shared_ptr 呢?

Since Scott Meyers did not show the complete assignment in the previous example, I thought the shared_ptr's assign operator is overloaded that one can do this:

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

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

But I tried with boost's implementation it doesn't work this way. Then what is the sense to have null shared_ptr?

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

I am almost sure that I am missing something here, someone help me out of it please.

我几乎可以肯定我在这里遗漏了一些东西,请有人帮助我。

ps. more about the initialization and assignment of a shared_ptr

附:有关 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;
}

this example can not be compiled by g++ (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2and the latest boost:

这个例子不能被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

回答by bdonlan

There is no need to use that hack to get a null (empty) shared_ptr. Simply use the default constructor:

无需使用该 hack 来获取 null (empty) shared_ptr。只需使用默认构造函数:

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

To assign a pointer to a shared_ptr, either do it at construction time:

要为 a 分配指针shared_ptr,请在构造时进行:

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

Or use the .reset()function:

或者使用.reset()函数:

pInt.reset(new Investment);

It's possible that the author of that article may have intended to provide a custom deleter (getRidOfInvestment). However, the deleter function is reset when .reset()is called, or when otherwise the inner pointer is changed. If you want a custom deleter, you must pass it to .reset()upon creation of the shared_ptr.

该文章的作者可能打算提供自定义删除器 ( getRidOfInvestment)。然而,删除器函数在.reset()被调用时被重置,或者当内部指针被改变时。如果您想要自定义删除器,则必须.reset()在创建shared_ptr.

One pattern you might want to use to make this more foolproof is a custom creation function:

您可能想要使用的一种模式来使这更加万无一失,那就是自定义创建函数:

class Investment {
protected:
  Investment();
  // ...
public:
  static shared_ptr<Investment> create();
};

shared_ptr<Investment> Investment::create() {
  return shared_ptr<Investment>(new Investment, getRidOfInvestment);
}

Later:

之后:

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

This ensures you will always have the correct destructor function attached to the shared_ptrs created from Investments.

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

回答by naumcho

It's the same reason to have a null raw pointer - e.g.

拥有空原始指针的原因相同 - 例如

say you have:

说你有:

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;
  }
}

This allows you to do:

这允许您执行以下操作:

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

回答by Kerrek SB

There are tons of reasons you might like objects to be default constructible. First and foremost you'd like the smart pointer to be as similar as possible to a raw pointer, and since you can say int * p;(and get an undefined, uninitialized pointer), you can also say shared_ptr<int> p;and get a pointer that doesn't point anywhere (but you get to test it with !).

您可能喜欢对象默认可构造的原因有很多。首先,您希望智能指针尽可能类似于原始指针,并且由于您可以说int * p;(并获得一个未定义的、未初始化的指针),您还可以说shared_ptr<int> p;并获得一个不指向任何地方的指针(但你可以用 来测试它!)。

One of the most compelling reasons is possibly that you can make containers with shared_ptrs, and you can fill the containers without assigning pointees right there and then.

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