在一個項目上工作時,當傳入的對象保證超時(就內存使用期限而言)收件人對象時,通過其構造函數將對象傳遞給另一個對象時,我遇到了一個有趣的問題。請記住,我仍然在學習C++ 11/C++ 14的入門知識,所以我在尋找有建設性的討論,這將有助於我用C++ 11/C++來理解內存管理和生命週期。 C++ 14風格的語義。如果一個對象被保證超出其包含的對象時應該如何存儲?
對於這個問題的設置如下:
class TopLevelClass {
public:
void someMethod (int someValue) {
// Do some work
}
std::unique_ptr<Context> getContext() {
return std::make_unique<Context>(this);
}
};
class Context {
public:
Context (TopLevelClass* tlc) : _tlc(tlc) {}
void call (int value) {
// Perform some work and then call the top level class...
_tlc->someMethod(value);
}
protected:
TopLevelClass* _tlc;
};
雖然這種設置有效的替代方案將是在TopLevelClass
作爲參數傳遞到Context
類的call
方法,這是不可能的在我正在說明的場景:訪問Context
對象的客戶端代碼可能無法訪問TopLevelClass
對象。
雖然上面說明的代碼功能正確,但我覺得存在代碼異味。也就是說,將TopLevelClass
對象的句柄存儲爲原始指針並不能表明Context
類不負責管理此指針的生存期(因爲在這種情況下,TopLevelClass
保證會超過任何Context
對象)。此外,使用C++ 11,我對使用原始指針而不是智能指針猶豫不決(按照Scott Meyer在Effective Modern C++中的建議)。
我探索的另一種方法是使用共享指針將句柄傳遞給TopLevelClass
,並將該句柄作爲共享指針存儲在Context
類中。這要求TopLevelClass
以下面的方式從std::enabled_shared_from_this
繼承:
class TopLevelClass : public std::enable_shared_from_this<TopLevelClass> {
public:
// Same "someMethod(int)" as before...
std::unique_ptr<Context> getContext() {
return std::make_unique<Context>(shared_from_this());
}
};
class Context {
public:
Context (std::shared_ptr<TopLevelClass> tlc) : _tlc(tlc) {}
// Same "call(int)" as before...
protected:
std::shared_ptr<TopLevelClass> _tlc;
};
這樣做的缺點的方法是,除非存在對TopLevelClass
先驗一個std::shared_ptr
,則std::bad_weak_ptr
會拋出異常(有關詳細信息,見this post)。因爲在我的情況下,在代碼中沒有創建std::shared_ptr<TopLevelClass>
,所以我不能使用std::enable_shared_from_this<T>
方法:根據我的項目要求,我僅限於使用static
原始指針返回TopLevelClass
的單個實例,如下所示
static TopLevelClass* getTopLevelClass() {
return new TopLevelClass();
}
是否有存在傳達的事實,Context
不負責管理其句柄TopLevelClass
情況下,因爲TopLevelClass
將保證活得比任何Context
對象的方法?我也對改變設計的建議持開放態度,只要設計更改不會過度複雜化上述設計的簡單性(即創建許多不同的類以簡單地傳遞進入構造函數Context
的單指針)。
謝謝你的幫助。
不是傳遞一個指針,而是傳遞並存儲一個引用。 – clcto
有什麼理由不能包裝getTopLevelClass函數嗎?如果有,請參考。 –
'getTopLevelClass()'是邪惡的。從簽名你可能會期望它返回一個單身人士,但實際上它返回一個擁有的原始指針到一個新的對象,每次你打電話時,調用者必須記得刪除! –