這是否泄漏記憶?
是。 myObj
的分配將調用默認的複製分配操作符,因爲您沒有提供覆蓋。因此,會執行逐個成員的副本,並且分配目標的myPtr
實例將被來自分配源的myPtr
實例覆蓋。這裏介紹兩個問題,違反了Rule of Three/Five/Zero的一個或多個部件時,經常遇到:
- 您失去從分配的目標原來
myPtr
內容。因此,該指針唯一引用的原始內存被泄漏。
- 您現在的分享相同的指針值在兩個
myPtr
成員:來源和分配操作的目標。
後者特別令人不安,因爲myObj
在TestObject
構造函數中完成賦值後立即離開範圍。在這樣做的時候,myObj
將被銷燬,並且與此同時,它被釋放了myPtr
。此外,myObj
通過在到該構造函數值,而不是引用,所以隱式副本已經可能發生(由於右值移動語義,缺乏副本)。因此, MyObj
對象很可能被吊裝myPtr
所有引用相同的內存,並儘快發佈一個它,其餘的都在不知不覺中提升晃來晃去指針。任何解引用或這些指針的調用將調用未定義的行爲。
給本地對象調用分配對象的析構函數嗎?
只有調用了析構函數才能與它們同名。也就是說,只有當一個對象被破壞被破壞時(手動調用析構函數進行放置 - 新的語義)時纔會調用它們。除非引入臨時對象,否則複製分配不會執行該操作,而代碼中則不是這種情況。
如果編譯器直接在構造函數中賦值,編譯器是否會優化對象實例變量的賦值?
不,但member initialization list可以在這方面提供幫助。
現代C++編程技術經常使用RAII來完成你彷彿是試圖以多種方式,這取決於你真正想要達到的目標。
唯一數據每個實例
如果目標是每個實例獨有的動態數據,您可與std::vector<char>
,或者乾脆std::string
容易做到這一點,取決於底層需求。兩者都是RAII數據類型,通常對於動態內存管理需求而言是充足的。
class MyObj
{
std::vector<char> myData;
public:
MyObj() : myData(30)
{
}
}
class TestObject
{
MyObj _myObj;
public:
TestObject(MyObj myObj)
: _myObj(std::move(myObj))
{
}
};
這消除MyObj
需要析構函數,並利用移動語義以及在TestObject
構造上述成員初始化列表。 MyObj
的所有實例都將提升一個不同的向量char
。 MyObj
和TestObject
的所有分配操作都使用默認實現。
分配共享內存
不太可能你想要這個,但它是沒有最不具有可行性:
class MyObj
{
std::shared_ptr<char> myPtr;
public:
MyObj() : myPtr(new char[30])
{
}
};
class TestObject
{
MyObj _myObj;
public:
TestObject(MyObj myObj)
: _myObj(std::move(myObj))
{
}
};
類似的代碼,但不同的成員類型。現在myPtr
是shared pointer到char
的數組。任何分配給不同的myPtr
都將加入共享列表。簡而言之,分配意味着兩個對象都參考相同的數據,並且引用計數可以確保最後一個人能夠清除混亂。
注意:使用像這樣的共享指針可能導致內存泄漏,因爲new
可能會成功,但共享指針的共享數據塊可能會引發異常。這是在C++ 17, 其中std::make_shared
支持數組分配
這些做什麼,你可能會嘗試完成的只是一些方法解決。我鼓勵您在所提供的鏈接和本網站上閱讀關於Rule of Three/Five/Zero和約RAII的概念。有很多例子可能會回答您可能遇到的更多問題。
「這是否泄漏記憶?」你的C++教科書對此有何評論? –
這兩個泄漏內存*和*最終雙釋放內存。總之,你會被迫使這個*更多*錯誤比現在。 – WhozCraig
爲了不存在泄漏問題或雙重問題,您需要遵循[rule-of-5](http://en.cppreference.com/w/cpp/language/rule_of_three)。或者走最佳路線並使用'std :: unique_ptr' – Justin