我有一个层次结构,其中A
是一个抽象类,B
,C
和D
是A
的后代。我有一个类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
的子类。我这样做了吗?
答案 0 :(得分:5)
你必须什么都不做。当您将新创建的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
第一个指针在创建第二个指针之后被破坏(更具体地说,在分配时;第一个指针在第一个指针递减的位置)。