我正在尝试在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的理解是,它实际上只指出 my code 范围内的问题,所以如果标准库正在删除依赖项,那么valgrind可能无法反映出来。然而,当我使用围绕一个普通类(没有依赖项)的智能指针对一个简单的程序运行valgrind时,它不会显示任何丢失的内存。
我还会注意到,我在stackoverflow上看到的一些例子对我没用,比如不在A的初始化列表中调用std::move
。而且我想避免传递任何原始指针。
答案 0 :(得分:0)
我正在使用不包含make_unique的g ++ 4.8.5但是我添加了Herb Sutter的建议make_unique implementation并在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实现?
答案 1 :(得分:0)
我在所有构造函数和析构函数中使用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()
我正在为每个析构函数计算一个构造函数。你对编译器有同样的看法吗?如果是这样,一切都很好。