使用工厂模式的地图泄漏内存,解决方案?
Leaking memory with a map using the factory pattern, solution?
class Factory
{
public:
Base* create() { return new Rand();}
Base* create(double value) { return new Op(value); }
Base* create(const std::string& comp, Base* x, Base* y)
{
/*
std::map<std::string, Base*> map_CreateFuncs = {
{ "+", new Add(x,y) },
{ "-", new Sub(x,y) },
{ "*", new Mult(x,y) },
{ "/", new Div(x,y) },
{ "**", new Pow(x,y) }
};
return (map_CreateFuncs.count(comp) == 1) ? map_CreateFuncs[comp] : nullptr;
*/
if (comp == "+") return new Add(x,y);
else if (comp == "-") return new Sub(x,y);
else if (comp == "*") return new Mult(x,y);
else if (comp == "/") return new Div(x,y);
else if (comp == "**") return new Pow(x,y);
else return nullptr;
}
};
使用 if/elseif 的作品 ~ 没有内存泄漏。
但我想使用我开始使用的地图方法。
想知道使用地图实现我的 create(string, Base*, Base*) 的正确方法是什么。
我已经阅读了使用 typedef 的代码,但我无法理解它的实现。
除非有非常具体的原因要使用原始指针,否则请考虑始终默认使用 std::unique_ptr
。使用智能指针既可以避免内存泄漏,又可以清楚地记录所有权模型。例如,当您创建 Add(x, y)
时,是否应该将 x
和 y
的所有权转移给新创建的对象,或者所有权可能与其他一些实例共享?如果是后者,请考虑 std::shared_ptr
.
您可能不想每次都为所有可用操作创建 class 个实例。相反,您可以通过存储一个对象来引入惰性求值,该对象将操作映射到创建适当 class 个实例的工厂函数。
总的来说,这看起来有点像这样:
class Base {
public:
virtual ~Base() = 0;
};
class Add : public Base {
public:
static std::unique_ptr<Base> create(std::unique_ptr<Base> x, std::unique_ptr<Base> y);
private:
// Constructor is private so that the user can only create smart pointers holding instances of Add.
Add(std::unique_ptr<Base> x, std::unique_ptr<Base> y);
};
class Factory
{
public:
std::unique_ptr<Base> create(const std::string& comp, std::unique_ptr<Base> x, std::unique_ptr<Base> y)
{
using FactoryMethod = std::function<std::unique_ptr<Base>(std::unique_ptr<Base>, std::unique_ptr<Base>)>;
static std::map<std::string, FactoryMethod> map_CreateFuncs = {
{ std::string("+"), FactoryMethod([](std::unique_ptr<Base> x, std::unique_ptr<Base> y){
return Add::create(std::move(x), std::move(y)); })},
// Other operations ...
};
const auto factory_method_it = map_CreateFuncs.find(comp);
if (factory_method_it == map_CreateFuncs.end()) {
return nullptr;
}
return (factory_method_it->second)(std::move(x), std::move(y));
}
};
请记住,std::map
和 std::function
可能会在简单的 if
-else
子句上引入一些开销。
class Factory
{
public:
Base* create() { return new Rand();}
Base* create(double value) { return new Op(value); }
Base* create(const std::string& comp, Base* x, Base* y)
{
/*
std::map<std::string, Base*> map_CreateFuncs = {
{ "+", new Add(x,y) },
{ "-", new Sub(x,y) },
{ "*", new Mult(x,y) },
{ "/", new Div(x,y) },
{ "**", new Pow(x,y) }
};
return (map_CreateFuncs.count(comp) == 1) ? map_CreateFuncs[comp] : nullptr;
*/
if (comp == "+") return new Add(x,y);
else if (comp == "-") return new Sub(x,y);
else if (comp == "*") return new Mult(x,y);
else if (comp == "/") return new Div(x,y);
else if (comp == "**") return new Pow(x,y);
else return nullptr;
}
};
使用 if/elseif 的作品 ~ 没有内存泄漏。 但我想使用我开始使用的地图方法。
想知道使用地图实现我的 create(string, Base*, Base*) 的正确方法是什么。
我已经阅读了使用 typedef 的代码,但我无法理解它的实现。
除非有非常具体的原因要使用原始指针,否则请考虑始终默认使用
std::unique_ptr
。使用智能指针既可以避免内存泄漏,又可以清楚地记录所有权模型。例如,当您创建Add(x, y)
时,是否应该将x
和y
的所有权转移给新创建的对象,或者所有权可能与其他一些实例共享?如果是后者,请考虑std::shared_ptr
.您可能不想每次都为所有可用操作创建 class 个实例。相反,您可以通过存储一个对象来引入惰性求值,该对象将操作映射到创建适当 class 个实例的工厂函数。
总的来说,这看起来有点像这样:
class Base {
public:
virtual ~Base() = 0;
};
class Add : public Base {
public:
static std::unique_ptr<Base> create(std::unique_ptr<Base> x, std::unique_ptr<Base> y);
private:
// Constructor is private so that the user can only create smart pointers holding instances of Add.
Add(std::unique_ptr<Base> x, std::unique_ptr<Base> y);
};
class Factory
{
public:
std::unique_ptr<Base> create(const std::string& comp, std::unique_ptr<Base> x, std::unique_ptr<Base> y)
{
using FactoryMethod = std::function<std::unique_ptr<Base>(std::unique_ptr<Base>, std::unique_ptr<Base>)>;
static std::map<std::string, FactoryMethod> map_CreateFuncs = {
{ std::string("+"), FactoryMethod([](std::unique_ptr<Base> x, std::unique_ptr<Base> y){
return Add::create(std::move(x), std::move(y)); })},
// Other operations ...
};
const auto factory_method_it = map_CreateFuncs.find(comp);
if (factory_method_it == map_CreateFuncs.end()) {
return nullptr;
}
return (factory_method_it->second)(std::move(x), std::move(y));
}
};
请记住,std::map
和 std::function
可能会在简单的 if
-else
子句上引入一些开销。