繁体   English   中英

C ++中带有智能指针的依赖注入

[英]Dependency injection w/ smart pointers in C++

我正在尝试在C ++项目中实现依赖项注入模式,手动执行注入(无框架)。 因此,我正在使用工厂函数手动创建依赖项,并将其传递给使用它们的类。 我的问题是,当依赖关系图的根(本身是由智能指针管理的类实例)超出范围时,其依赖关系(在类中引用的智能指针)不会被破坏(valgrind显示丢失的内存块) 。

我看到的只是这样的基本示例,其中A类依赖于B类:

class B{
public:
    B() {}
    ~B() {}
};

class A{

    std::unique_ptr<B> b_;

public:

    A(std::unique_ptr<B> b) : b_(std::move(b)) { }
    ~A(){}
};

namespace A_Factory {
    std::unique_ptr<A> getInstance(){
        return std::make_unique<A>(std::make_unique<B>());
    }
}

int main(void){
    auto a = A_Factory::getInstance();
    //do some A stuff
} //a goes out of scope and gets deleted?

因此,在此示例中,我使用A_Factory::getInstance获取A,因此使用A的任何内容都不知道A是如何创建的,也不知道A如何创建其依赖项。 据我了解,使用智能指针,它们将在超出范围时自动删除, 希望一旦根超出范围, 它们便会链接依赖图 如果必须实现代码以消除依赖关系,那么智能指针并不会带来太多好处。

因此,我无法确定我是否没有使用智能指针正确地进行设置,或者valgrind并未告诉我我的意思。 我对valgrind的理解是,它实际上仅指出了代码范围内的问题,因此,如果标准库正在删除依赖项,则valgrind可能无法反映这一点。 但是,当我使用包裹在琐碎类(没有依赖项)上的智能指针对一个简单程序运行valgrind时,它不会显示任何丢失的内存。

我还将注意到,在这里我在stackoverflow上看到的一些示例对我没有用,例如不在A的初始化列表中调用std::move 而且我想避免传递任何原始指针。

我正在使用不包含make_unique的g ++ 4.8.5,但是我添加了Herb Sutter的建议的make_unique实现,并在显示未泄漏的valgrind下运行测试。

#include <iostream>
#include <cstdlib>
#include <memory>

using namespace std;

template<typename T, typename ...Args>
std::unique_ptr<T> make_unique(Args&& ...args)
{
   return std::unique_ptr<T>(new T ( std::forward<Args>(args)...));
}

class B{
public:
    B() {}
    ~B() {}
};

class A{

    std::unique_ptr<B> b_;

public:

    A(std::unique_ptr<B> b) : b_(std::move(b)) { }
    ~A(){}
};

namespace A_Factory {
    std::unique_ptr<A> getInstance(){
        return make_unique<A>(make_unique<B>());
    }
}

int main(void){
   auto a = A_Factory::getInstance();
}

也许您的问题源于正在使用的编译器中的make_unique实现?

我已经在所有构造函数和析构函数中使用print语句对代码进行了检测。 此外,我禁用了所有编译器生成的构造函数,以确保它们不运行:

#include <iostream>
#include <memory>

class B{
public:
    B() {std::cout << "B()\n";}
    ~B() {std::cout << "~B()\n";}
    B(const B&) = delete;
};

class A{

    std::unique_ptr<B> b_;

public:

    A(std::unique_ptr<B> b) : b_(std::move(b)) {std::cout << "A()\n";}
    ~A(){std::cout << "~A()\n";}
    A(const A&) = delete;
};

namespace A_Factory {
    std::unique_ptr<A> getInstance(){
        return std::make_unique<A>(std::make_unique<B>());
    }
}

int main(void){
    auto a = A_Factory::getInstance();
    //do some A stuff
}

该程序为我输出:

B()
A()
~A()
~B()

我正在为每个析构函数计数一个构造函数。 您在编译器中看到相同的东西吗? 如果是这样,一切都很好。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM