shared_ptr 和构建器模式的 C++ 运行时错误
C++ runtime error with shared_ptr and builder pattern
我正在研究具有共享指针和构建器模式的 C++ 语言。
我编写了以下无法运行的代码,但我不明白为什么它会发出 运行 次错误。
你能告诉我为什么它不能正常工作吗?我该如何解决这个问题才能正常工作?
#include <iostream>
#include <memory>
#include <string>
using namespace std;
class Popup
{
public:
Popup(int value, string str){
this->v = value;
this->str = str;
}
virtual void print() = 0;
int v;
string str;
};
typedef shared_ptr<Popup> PopupPtr;
class PopupA : public Popup
{
public:
PopupA(int v, string str) : Popup(v, str) { }
virtual void print() {
cout << "PopupA" << endl;
}
};
typedef shared_ptr<PopupA> PopupAPtr;
class PopupB : public Popup
{
public:
PopupB(int v, string str) : Popup(v, str) { }
virtual void print() {
cout << "PopupB" << endl;
}
};
typedef shared_ptr<PopupB> PopupBPtr;
class Builder
{
public:
PopupPtr popupPtr;
Builder() { };
shared_ptr<Builder> init(int value, string str) {
shared_ptr<Builder> builder;
switch (value)
{
case 1:
popupPtr = PopupAPtr(new PopupA(value, str));
break;
case 2:
popupPtr = PopupBPtr(new PopupB(value, str));
break;
default:
cout << "default error" << endl;
break;
}
if (popupPtr) {
builder = shared_ptr<Builder>(this);
}
else {
cout << "popup is null" << endl;
}
if (!builder) {
cout << "builder is null" << endl;
}
return builder;
}
PopupPtr build()
{
if (!popupPtr) {
cout << "popup is null" << endl;
}
return PopupPtr(popupPtr);
}
};
typedef shared_ptr<Builder> BuilderPtr;
int main()
{
BuilderPtr builderPtr = BuilderPtr(new Builder());
PopupPtr popupPtr1 = builderPtr->init(1, "111111111111")->build();
popupPtr1->print();
PopupPtr popupPtr2 = builderPtr->init(2, "222222222222")->build();
popupPtr2->print();
return 0;
}
提前感谢您的回答,抱歉我的英语不好。如果您不明白我的问题,请发表评论。
你的问题是这一行:
builder = shared_ptr<Builder>(this);
这将不会创建已经跟踪this
的std::shared_ptr
的副本,也不会影响它的引用计数。这将创建一个全新的共享指针,它将独立跟踪 this
,当两个引用计数都为零时导致双重删除。
幸运的是,标准库以std::shared_from_this
的形式提供了解决这个问题的方法。
首先,您需要为您的 class:
启用此功能
class Builder : std::enable_shared_from_this<Builder>
{
//...
};
然后不是从 this
创建新的 std::shared_ptr
,而是调用 std::shared_from_this
:
builder = std::shared_from_this();
我正在研究具有共享指针和构建器模式的 C++ 语言。
我编写了以下无法运行的代码,但我不明白为什么它会发出 运行 次错误。
你能告诉我为什么它不能正常工作吗?我该如何解决这个问题才能正常工作?
#include <iostream>
#include <memory>
#include <string>
using namespace std;
class Popup
{
public:
Popup(int value, string str){
this->v = value;
this->str = str;
}
virtual void print() = 0;
int v;
string str;
};
typedef shared_ptr<Popup> PopupPtr;
class PopupA : public Popup
{
public:
PopupA(int v, string str) : Popup(v, str) { }
virtual void print() {
cout << "PopupA" << endl;
}
};
typedef shared_ptr<PopupA> PopupAPtr;
class PopupB : public Popup
{
public:
PopupB(int v, string str) : Popup(v, str) { }
virtual void print() {
cout << "PopupB" << endl;
}
};
typedef shared_ptr<PopupB> PopupBPtr;
class Builder
{
public:
PopupPtr popupPtr;
Builder() { };
shared_ptr<Builder> init(int value, string str) {
shared_ptr<Builder> builder;
switch (value)
{
case 1:
popupPtr = PopupAPtr(new PopupA(value, str));
break;
case 2:
popupPtr = PopupBPtr(new PopupB(value, str));
break;
default:
cout << "default error" << endl;
break;
}
if (popupPtr) {
builder = shared_ptr<Builder>(this);
}
else {
cout << "popup is null" << endl;
}
if (!builder) {
cout << "builder is null" << endl;
}
return builder;
}
PopupPtr build()
{
if (!popupPtr) {
cout << "popup is null" << endl;
}
return PopupPtr(popupPtr);
}
};
typedef shared_ptr<Builder> BuilderPtr;
int main()
{
BuilderPtr builderPtr = BuilderPtr(new Builder());
PopupPtr popupPtr1 = builderPtr->init(1, "111111111111")->build();
popupPtr1->print();
PopupPtr popupPtr2 = builderPtr->init(2, "222222222222")->build();
popupPtr2->print();
return 0;
}
提前感谢您的回答,抱歉我的英语不好。如果您不明白我的问题,请发表评论。
你的问题是这一行:
builder = shared_ptr<Builder>(this);
这将不会创建已经跟踪this
的std::shared_ptr
的副本,也不会影响它的引用计数。这将创建一个全新的共享指针,它将独立跟踪 this
,当两个引用计数都为零时导致双重删除。
幸运的是,标准库以std::shared_from_this
的形式提供了解决这个问题的方法。
首先,您需要为您的 class:
启用此功能class Builder : std::enable_shared_from_this<Builder>
{
//...
};
然后不是从 this
创建新的 std::shared_ptr
,而是调用 std::shared_from_this
:
builder = std::shared_from_this();