使用工厂模式的地图泄漏内存,解决方案?

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 的代码,但我无法理解它的实现。

  1. 除非有非常具体的原因要使用原始指针,否则请考虑始终默认使用 std::unique_ptr。使用智能指针既可以避免内存泄漏,又可以清楚地记录所有权模型。例如,当您创建 Add(x, y) 时,是否应该将 xy 的所有权转移给新创建的对象,或者所有权可能与其他一些实例共享?如果是后者,请考虑 std::shared_ptr.

  2. 您可能不想每次都为所有可用操作创建 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::mapstd::function 可能会在简单的 if-else 子句上引入一些开销。