C++ 如何在decorator模式实现中正确使用shared_ptr?
我在下面的代码中遇到内存泄漏问题。我知道有一些流动。但不确定。如何在这些场景中使用共享的ptr?如果我需要添加更多的装饰,比如巧克力比萨冰淇淋,如何正确地传递指针,使其在出口处被删除C++ 如何在decorator模式实现中正确使用shared_ptr?,c++,design-patterns,memory-leaks,decorator,shared-ptr,C++,Design Patterns,Memory Leaks,Decorator,Shared Ptr,我在下面的代码中遇到内存泄漏问题。我知道有一些流动。但不确定。如何在这些场景中使用共享的ptr?如果我需要添加更多的装饰,比如巧克力比萨冰淇淋,如何正确地传递指针,使其在出口处被删除 class AbstractCream { public: virtual void ShowFlavour() = 0; virtual ~AbstractCream() { cout << endl << "AbstractCream-DT
class AbstractCream
{
public:
virtual void ShowFlavour() = 0;
virtual ~AbstractCream()
{
cout << endl << "AbstractCream-DTOR";
}
};
class IceCream :public AbstractCream
{
public:
void ShowFlavour()
{
cout << "IceCream";
}
~IceCream()
{
cout << endl << "IceCream Dtor";
}
};
class DecoratorCream :public AbstractCream
{
private:
std::shared_ptr<AbstractCream> AbCream;
public:
DecoratorCream(std::shared_ptr<AbstractCream>abs) :AbCream(abs)
{}
void ShowFlavour()
{
AbCream->ShowFlavour();
}
virtual ~DecoratorCream()
{
cout << endl << "DecoratorCream-DTOR";
}
};
class ChocolateCream : public DecoratorCream
{
public:
ChocolateCream(std::shared_ptr<AbstractCream>abs) :DecoratorCream(abs)
{}
void ShowFlavour()
{
cout << "CholocateCream added..";
DecoratorCream::ShowFlavour();
}
~ChocolateCream()
{
cout << endl << "ChocolateCream-DTOR";
}
};
class PistaCream : public DecoratorCream
{
public:
PistaCream(std::shared_ptr<AbstractCream> abs) :DecoratorCream(abs)
{}
void ShowFlavour()
{
cout << "PistaCream added..";
DecoratorCream::ShowFlavour();
}
~PistaCream()
{
cout << endl << "PistaCream-DTOR";
}
};
class StrawberryCream : public DecoratorCream
{
public:
StrawberryCream(std::shared_ptr<AbstractCream> abs) :DecoratorCream(abs)
{}
void ShowFlavour()
{
cout << "StrawberryCream added..";
DecoratorCream::ShowFlavour();
}
~StrawberryCream()
{
cout << endl << "StrawberryCream-DTOR";
}
};
int main()
{
std::shared_ptr <AbstractCream> ice1( new IceCream());
std::shared_ptr <PistaCream> pista1(new PistaCream(ice1));
std::shared_ptr <AbstractCream> ice2(new IceCream());
std::shared_ptr <ChocolateCream>choco1( new ChocolateCream(ice2));
pista1->ShowFlavour();
cout << endl;
choco1->ShowFlavour();
cout << endl;
getchar();
_CrtDumpMemoryLeaks();
return 0;
}
类抽象
{
公众:
虚拟void showFlavor()=0;
虚拟~AbstractCream()
{
cout问题似乎不在于类中使用的std::shared_ptr
:这在语义上似乎是正确的(尽管代码太多,无法详细查看)。相反,我认为您的main()
是错误的:您试图在对象仍处于活动状态的时间点确定内存泄漏。我不是Windows程序,但我非常确定\u CrtDumpMemoryLeak()
不知道std::shared\u ptr
并简单地报告新的ed内存,它还不是删除d
有几种简单的方法可以更改main()
,以避免出现问题:
将对象的分配放入块中,并在块后报告内存泄漏:
int main() {
{
std::shared_ptr <AbstractCream> ice1( new IceCream());
// ...
}
_CrtDumpMemoryLeaks();
}
报告早期构造的对象的析构函数的内存泄漏,例如main()
:
如果您也想在其他构造函数中按值传递参数,那么至少应该,std::move(…)
参数。这样做可以避免引用计数,但仍然无法避免所有工作,因为它需要在每个级别上构造/销毁std::shared\u ptr
。但是,至少可以避免同步维护引用计数
因为我提到了一个性能问题:。它对您没有多大好处。在您的使用中,它只会减慢程序的速度。问题似乎不是在您的类中使用std::shared\u ptr
:这似乎在语义上是正确的(但代码太多,无法详细查看)。相反,我认为您的main()
是错误的:您试图在对象仍处于活动状态的时间点确定内存泄漏。我不是Windows程序,但我非常确定\u CrtDumpMemoryLeak()
不知道std::shared\u ptr
并简单地报告新的ed内存,它还不是删除d
class AbstractCream
{
public:
virtual void ShowFlavour() = 0;
virtual ~AbstractCream()
{
cout << endl << "AbstractCream-DTOR";
}
};
class IceCream :public AbstractCream
{
public:
void ShowFlavour()
{
cout << "IceCream";
}
~IceCream()
{
cout << endl << "IceCream Dtor";
}
};
class DecoratorCream :public AbstractCream
{
private:
std::shared_ptr<AbstractCream> AbCream;
public:
DecoratorCream(const std::shared_ptr<AbstractCream> &abs) :AbCream(abs)
{}
void ShowFlavour()
{
AbCream->ShowFlavour();
}
virtual ~DecoratorCream()
{
cout << endl << "DecoratorCream-DTOR";
}
};
class ChocolateCream : public DecoratorCream
{
public:
ChocolateCream(const std::shared_ptr<AbstractCream>& abs) :DecoratorCream(abs)
{}
void ShowFlavour()
{
cout << "CholocateCream added..";
DecoratorCream::ShowFlavour();
}
~ChocolateCream()
{
cout << endl << "ChocolateCream-DTOR";
}
};
class PistaCream : public DecoratorCream
{
public:
PistaCream(const std::shared_ptr<AbstractCream> &abs) :DecoratorCream(abs)
{}
void ShowFlavour()
{
cout << "PistaCream added..";
DecoratorCream::ShowFlavour();
}
~PistaCream()
{
cout << endl << "PistaCream-DTOR";
}
};
class StrawberryCream : public DecoratorCream
{
public:
StrawberryCream(const std::shared_ptr<AbstractCream>& abs) :DecoratorCream(abs)
{}
void ShowFlavour()
{
cout << "StrawberryCream added..";
DecoratorCream::ShowFlavour();
}
~StrawberryCream()
{
cout << endl << "StrawberryCream-DTOR";
}
};
//-------------------dec--------------------------------------------------------------//
struct DummyToLeakCheck
{
public:
~DummyToLeakCheck()
{
_CrtDumpMemoryLeaks();
}
};
int main()
{
DummyToLeakCheck myLeakChecker;
std::shared_ptr <AbstractCream> ice1( new IceCream());
std::shared_ptr <PistaCream> pista1(new PistaCream(ice1));
std::shared_ptr <AbstractCream> ice2(new IceCream());
std::shared_ptr <ChocolateCream>choco1( new ChocolateCream(ice2));
std::shared_ptr <StrawberryCream>straw1(new StrawberryCream(choco1));
pista1->ShowFlavour();
cout << endl;
choco1->ShowFlavour();
cout << endl;
straw1->ShowFlavour();
cout << endl;
getchar();
return 0;
}
有几种简单的方法可以更改main()
,以避免出现问题:
将对象的分配放入块中,并在块后报告内存泄漏:
int main() {
{
std::shared_ptr <AbstractCream> ice1( new IceCream());
// ...
}
_CrtDumpMemoryLeaks();
}
报告早期构造的对象的析构函数的内存泄漏,例如main()
:
如果您也想在其他构造函数中按值传递参数,那么至少应该,std::move(…)
参数。这样做可以避免引用计数,但仍然无法避免所有工作,因为它需要在每个级别上构造/销毁std::shared\u ptr
。但是,至少可以避免同步维护引用计数
因为我提到了一个性能问题:。它对您没有多大好处。在您使用时,它只会减慢程序的速度。class AbstractCream
class AbstractCream
{
public:
virtual void ShowFlavour() = 0;
virtual ~AbstractCream()
{
cout << endl << "AbstractCream-DTOR";
}
};
class IceCream :public AbstractCream
{
public:
void ShowFlavour()
{
cout << "IceCream";
}
~IceCream()
{
cout << endl << "IceCream Dtor";
}
};
class DecoratorCream :public AbstractCream
{
private:
std::shared_ptr<AbstractCream> AbCream;
public:
DecoratorCream(const std::shared_ptr<AbstractCream> &abs) :AbCream(abs)
{}
void ShowFlavour()
{
AbCream->ShowFlavour();
}
virtual ~DecoratorCream()
{
cout << endl << "DecoratorCream-DTOR";
}
};
class ChocolateCream : public DecoratorCream
{
public:
ChocolateCream(const std::shared_ptr<AbstractCream>& abs) :DecoratorCream(abs)
{}
void ShowFlavour()
{
cout << "CholocateCream added..";
DecoratorCream::ShowFlavour();
}
~ChocolateCream()
{
cout << endl << "ChocolateCream-DTOR";
}
};
class PistaCream : public DecoratorCream
{
public:
PistaCream(const std::shared_ptr<AbstractCream> &abs) :DecoratorCream(abs)
{}
void ShowFlavour()
{
cout << "PistaCream added..";
DecoratorCream::ShowFlavour();
}
~PistaCream()
{
cout << endl << "PistaCream-DTOR";
}
};
class StrawberryCream : public DecoratorCream
{
public:
StrawberryCream(const std::shared_ptr<AbstractCream>& abs) :DecoratorCream(abs)
{}
void ShowFlavour()
{
cout << "StrawberryCream added..";
DecoratorCream::ShowFlavour();
}
~StrawberryCream()
{
cout << endl << "StrawberryCream-DTOR";
}
};
//-------------------dec--------------------------------------------------------------//
struct DummyToLeakCheck
{
public:
~DummyToLeakCheck()
{
_CrtDumpMemoryLeaks();
}
};
int main()
{
DummyToLeakCheck myLeakChecker;
std::shared_ptr <AbstractCream> ice1( new IceCream());
std::shared_ptr <PistaCream> pista1(new PistaCream(ice1));
std::shared_ptr <AbstractCream> ice2(new IceCream());
std::shared_ptr <ChocolateCream>choco1( new ChocolateCream(ice2));
std::shared_ptr <StrawberryCream>straw1(new StrawberryCream(choco1));
pista1->ShowFlavour();
cout << endl;
choco1->ShowFlavour();
cout << endl;
straw1->ShowFlavour();
cout << endl;
getchar();
return 0;
}
{
公众:
虚拟void showFlavor()=0;
虚拟~AbstractCream()
{
cout类抽象
{
公众:
虚拟void showFlavor()=0;
虚拟~AbstractCream()
{
CUT作为一个旁注,您应该使用<代码> STD::MaMuxSudio,并考虑<代码> STD::UnQuyJPPT。您能详细说明一下吗?我的理解是UnQuyQPTR是有用的,如果我们有一个数组来清除相似或删除[]。作为一个旁注,您应该使用<代码> STD::MaxySuffy,并考虑<代码> STD::UnQuyJPPT。您能详细说明一下吗?我的理解是UnQuyQPTR是有用的,如果我们有一个数组来清除相似或删除[]。非常感谢你的帮助。这解决了内存检查问题。它实际上是在清除内存,但检查点正如你所说的是错误的。第二点,std::endl。在换行后打印有什么更好的选择呢?最后但并非最不重要的是,我仍然无法将嵌套的新指针传递给外部共享指针。我需要d首先使用另一个共享指针创建一个,然后必须将其传递给另一个以获得更多的包装(如果是装饰器)。这是否已导出?/*下面的代码示例演示如何尝试三层装饰*/std::shared_ptr ice2(new IceCream());std::shared_ptr choco1(new Chocolate(ice2));std::shared_ptr straw1(新草莓奶油(巧克力);@Anand:restd::endl
:只需使用'\n'
。如果你按照答案进行操作,你会发现推理和备选方案的一份相当全面的报告。它们是所需的对象:我不是特别擅长面向对象编程,但我认为可以预期你会将对象装饰在周围。@Dietm安:谢谢。现在我知道了避免使用std::endl的原因。@Dietman:非常感谢你的帮助。这解决了内存检查问题。事实上,它清除了内存,但检查点正如你所说的是错误的。第二点,std::endl。在换行后打印有什么更好的替代方案吗?最后但并非最不重要的是,我仍然无法使用pass嵌套了指向外部共享指针的新指针。我需要先用另一个共享指针创建一个指针,然后将它传递给另一个指针以获得更多的包裹数(如果是Decorator)。这是否已导出?/*下面的代码示例演示如何尝试三层装饰*/std::shared_ptr ice2(new IceCream());std::shared_ptr choco1(新巧克力冰淇淋(ice2));std::shared_ptr straw1(新草莓奶油(choco1));@Anand:restd::endl
:只需使用'\n'
。如果你按照答案进行操作,你会发现推理和替代方案有一个相当透彻的书面说明
DecoratorCream(std::shared_ptr<AbstractCream> abs)
: AbCream(std::move(abs)) {
}
class AbstractCream
{
public:
virtual void ShowFlavour() = 0;
virtual ~AbstractCream()
{
cout << endl << "AbstractCream-DTOR";
}
};
class IceCream :public AbstractCream
{
public:
void ShowFlavour()
{
cout << "IceCream";
}
~IceCream()
{
cout << endl << "IceCream Dtor";
}
};
class DecoratorCream :public AbstractCream
{
private:
std::shared_ptr<AbstractCream> AbCream;
public:
DecoratorCream(const std::shared_ptr<AbstractCream> &abs) :AbCream(abs)
{}
void ShowFlavour()
{
AbCream->ShowFlavour();
}
virtual ~DecoratorCream()
{
cout << endl << "DecoratorCream-DTOR";
}
};
class ChocolateCream : public DecoratorCream
{
public:
ChocolateCream(const std::shared_ptr<AbstractCream>& abs) :DecoratorCream(abs)
{}
void ShowFlavour()
{
cout << "CholocateCream added..";
DecoratorCream::ShowFlavour();
}
~ChocolateCream()
{
cout << endl << "ChocolateCream-DTOR";
}
};
class PistaCream : public DecoratorCream
{
public:
PistaCream(const std::shared_ptr<AbstractCream> &abs) :DecoratorCream(abs)
{}
void ShowFlavour()
{
cout << "PistaCream added..";
DecoratorCream::ShowFlavour();
}
~PistaCream()
{
cout << endl << "PistaCream-DTOR";
}
};
class StrawberryCream : public DecoratorCream
{
public:
StrawberryCream(const std::shared_ptr<AbstractCream>& abs) :DecoratorCream(abs)
{}
void ShowFlavour()
{
cout << "StrawberryCream added..";
DecoratorCream::ShowFlavour();
}
~StrawberryCream()
{
cout << endl << "StrawberryCream-DTOR";
}
};
//-------------------dec--------------------------------------------------------------//
struct DummyToLeakCheck
{
public:
~DummyToLeakCheck()
{
_CrtDumpMemoryLeaks();
}
};
int main()
{
DummyToLeakCheck myLeakChecker;
std::shared_ptr <AbstractCream> ice1( new IceCream());
std::shared_ptr <PistaCream> pista1(new PistaCream(ice1));
std::shared_ptr <AbstractCream> ice2(new IceCream());
std::shared_ptr <ChocolateCream>choco1( new ChocolateCream(ice2));
std::shared_ptr <StrawberryCream>straw1(new StrawberryCream(choco1));
pista1->ShowFlavour();
cout << endl;
choco1->ShowFlavour();
cout << endl;
straw1->ShowFlavour();
cout << endl;
getchar();
return 0;
}