C++ 使用工厂模式的映射泄漏内存,解决方案? 类工厂 { 公众: Base*create(){return new Rand();} Base*create(双值){返回新的Op(值);} 基本*创建(常量标准::字符串和组件,基本*x,基本*y) { /* std::map\u CreateFuncs={ {“+”,新添加(x,y)}, {“-”,新的子(x,y)}, {“*”,新的Mult(x,y)}, {“/”,新的Div(x,y)}, {**,新战俘(x,y)} }; 返回(map_CreateFuncs.count(comp)==1)?map_CreateFuncs[comp]:nullptr; */ if(comp==“+”)返回新的Add(x,y); else if(comp==“-”)返回新的子项(x,y); else if(comp==“*”)返回新的Mult(x,y); else if(comp==“/”)返回新的Div(x,y); 否则如果(comp==“**”)返回新的Pow(x,y); 否则返回空ptr; } };

C++ 使用工厂模式的映射泄漏内存,解决方案? 类工厂 { 公众: Base*create(){return new Rand();} Base*create(双值){返回新的Op(值);} 基本*创建(常量标准::字符串和组件,基本*x,基本*y) { /* std::map\u CreateFuncs={ {“+”,新添加(x,y)}, {“-”,新的子(x,y)}, {“*”,新的Mult(x,y)}, {“/”,新的Div(x,y)}, {**,新战俘(x,y)} }; 返回(map_CreateFuncs.count(comp)==1)?map_CreateFuncs[comp]:nullptr; */ if(comp==“+”)返回新的Add(x,y); else if(comp==“-”)返回新的子项(x,y); else if(comp==“*”)返回新的Mult(x,y); else if(comp==“/”)返回新的Div(x,y); 否则如果(comp==“**”)返回新的Pow(x,y); 否则返回空ptr; } };,c++,memory-leaks,factory-pattern,C++,Memory Leaks,Factory Pattern,使用if/elseif有效~无内存泄漏。 但是我想使用我开始使用的map方法 想知道使用映射实现我的create(string,Base*,Base*)的正确方法是什么 我读过使用typedef的代码,但我不理解它的实现 >P>除非使用原始指针,否则默认情况下总是考虑使用 STD::UNQuYYPTPT/。使用智能指针既可以避免内存泄漏,又可以清楚地记录所有权模型。例如,当您创建Add(x,y)时,x和y的所有权应该转移到新创建的对象,还是应该与其他一些实例共享所有权?在后一种情况下,考虑 S

使用if/elseif有效~无内存泄漏。 但是我想使用我开始使用的map方法

想知道使用映射实现我的create(string,Base*,Base*)的正确方法是什么

我读过使用typedef的代码,但我不理解它的实现

>P>除非使用原始指针,否则默认情况下总是考虑使用<代码> STD::UNQuYYPTPT/<代码>。使用智能指针既可以避免内存泄漏,又可以清楚地记录所有权模型。例如,当您创建
Add(x,y)
时,
x
y
的所有权应该转移到新创建的对象,还是应该与其他一些实例共享所有权?在后一种情况下,考虑<代码> STD::SysDypPTR < /代码> ./P>
  • 您可能不希望每次都为所有可用操作创建类实例。相反,您可以通过存储将操作映射到创建适当类实例的工厂函数的对象来引入延迟计算

  • 总的来说,这看起来有点像这样:

    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;
            }
    };
    
    类基{
    公众:
    virtual~Base()=0;
    };
    类添加:公共基{
    公众:
    静态std::unique_ptr create(std::unique_ptr x,std::unique_ptr y);
    私人:
    //构造函数是私有的,因此用户只能创建包含Add实例的智能指针。
    添加(std::unique_ptr x,std::unique_ptr y);
    };
    阶级工厂
    {
    公众:
    std::unique\u ptr create(常量std::string&comp,std::unique\u ptr x,std::unique\u ptr y)
    {
    使用FactoryMethod=std::function;
    静态std::map\u CreateFuncs={
    {std::string(“+”),FactoryMethod([](std::unique_ptr x,std::unique_ptr y){
    返回Add::create(std::move(x),std::move(y));}),
    //其他操作。。。
    };
    const auto factory_method_it=map_CreateFuncs.find(comp);
    if(factory\u method\u it==map\u CreateFuncs.end()){
    返回空ptr;
    }
    返回(工厂\方法\它->秒)(标准::移动(x),标准::移动(y));
    }
    };
    

    请记住,
    std::map
    std::function
    可能会在简单的
    if
    -
    else
    子句上引入一些开销。

    可能使用lambda函数?不要使用
    new
    。而是使用。它为您管理内存,因此不会泄漏。如果您不使用
    unique\u ptr
    ,则必须确定何时不再使用
    map
    ,并删除放入其中的所有对象。确定何时可以安全地
    删除
    。。。这是一个更烦人的编程问题,所以请使用
    unique\u ptr
    和其他智能指针来为您解决它,并确保契约完成。关于
    返回(map\u CreateFuncs.count(comp)==1)?map_CreateFuncs[comp]:nullptr您可以保存一个查找<代码>映射\u CreateFuncs.count(comp)==1)
    搜索映射<代码>地图\u CreateFuncs[comp]
    也会搜索地图<代码>自动查找=map\u CreateFuncs.find(comp)是一个搜索。然后你
    返回找到的!=映射_CreateFuncs.end()*it:nullptr
    也就是说,这可能根本不是您想要做的事情,如果您希望每次都返回一个新的
    Base
    派生对象,就像人们期望从工厂返回的那样,这就不是您想要做的事情。不过,需要更多地了解您的用例才能做出合理的回答。注意:
    x
    y
    可能比指针或
    unique\u ptr
    更适合作为引用传递。但是为什么操作数也是从
    基派生的呢?在搜索google时,我发现很多函数在每个派生函数中都使用了静态创建方法。我用我的实现避免了这一点。std::函数对我来说是新的,我想它可以满足我的需求,非常感谢@用户4581301关于这一点你可能是对的,我将进行实验,看看是否可以通过引用传递它们。我不熟悉这个替换原则,所以谢谢你的链接!至于为什么它来自于基地;Base只是一个抽象类,从中添加/减去/多个/除/幂继承~这最初是为复合模式完成的,现在它使用相同的元素,但使用工厂模式。我会发布我的源代码,但我只能想象它会收到多坏^;特别是解析器非常丑陋,我不认为我可以通过引用传递x,y——因为它们从基继承,因此可以是复合的。它基本上变成一棵树,其中每个操作符都是一个具有lhs/rhs的节点。基址可以是运算符或操作数,其中lhs/RH为空PTR。
    
    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));
        }
    };