簡體   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