我有一个层次结构,其中A是抽象类,而BCDA的后代。我有一个类Controller(MVC模式),它具有指向A的共享指针:

class Controller {

private:
 int it;
 std::shared_ptr<A> theBase;

public:
 void doCall();
//more code

}


doCall()内部,我这样做:

void doCall() {

  switch (it) {
    case 4:
      theBase = std::make_shared<B>( B(8) );
      break;
    case 3:
      theBase = std::make_shared<C>( C(6) );
      break;
    default:
      theBase = std::make_shared<D>( D(0) );
      break;
    }

  theBase->method();

}


这样,我可以正确使用智能指针,并可以使用继承根据it的值获取所需的类。

假设我将此代码称为:

Controller x;
x.doCall();
x.doCall();


我两次拨打doCall(),所以我要两次进入switch。这意味着std::make_shared被调用两次并分配给theBase。这样安全吗?

第一次调用doCall()时,我有一个共享指针。第二次我为std::shared_ptr分配另一个theBase时,我想知道:旧指针(第一个调用中的一个)被破坏了,并且创建了一个新指针吗?还是我必须做这样的事情?

if (*theBase != nullptr) {
  theBase.reset(); //delete the old one;
}

switch (it) { /* ... */}


每次调用doCall()时,我必须创建一个新对象,该对象是theBase的子类。我做得对吗?

最佳答案

你什么都不做。将新创建的shared_ptr分配给theBase时,旧的参考计数器将减少。但是旧的计数器是1(如果我们假设您未在其他地方引用它)。计数器达到0,并调用析构函数。

看下面的代码:

#include <stdio.h>
#include <memory>

class myClass
{
public:
    myClass(int i) : m_i(i) { printf("Constructed %d\n", m_i); }
    ~myClass() { printf("Destructed %d\n", m_i); }

    int m_i;
};

int main()
{
    std::shared_ptr<myClass> ptr = std::make_shared<myClass>(5);

    ptr = std::make_shared<myClass>(10);
}


输出为:

Constructed 5
Constructed 10
Destructed 5
Destructed 10


在创建第二个指针后立即销毁第一个指针(更具体而言,在分配指针时;第一个指针的计数器在此递减)。

08-24 18:08