我有一個任務,使用一個列表和一個使用兩個堆棧的Queue類來編寫Stacks類。我已經完成了任務,但在運行Valgrind的,我覺得,我在下面的代碼中的內存泄漏:堆棧/隊列中的內存泄漏C++
T Stack<T>::pop()
{
T *n = new T;
*n = myStack.front();
myStack.pop_front();
return *n;
}
我不能刪除指針後,我回吧,所以我不知道如何修理它。提前致謝。
我有一個任務,使用一個列表和一個使用兩個堆棧的Queue類來編寫Stacks類。我已經完成了任務,但在運行Valgrind的,我覺得,我在下面的代碼中的內存泄漏:堆棧/隊列中的內存泄漏C++
T Stack<T>::pop()
{
T *n = new T;
*n = myStack.front();
myStack.pop_front();
return *n;
}
我不能刪除指針後,我回吧,所以我不知道如何修理它。提前致謝。
你應該已經相當使用
T n = myStack.front();
製作副本,然後清除如果有的話裏面pop_front內存。
T Stack<T>::pop()
{
T ret = myStack.front();
myStack.pop_front();
return ret;
}
爲什麼你甚至需要使用新的?你可以像這樣做一個堆棧的最高值的副本:
T Stack<T>::pop()
{
T n = myStack.front();
myStack.pop_front();
return n;
}
所以沒有分配和沒有泄漏;
在你的地方,我會停止使用原始指針並更改爲shared_ptr。是更安全。
你有多個答案給出正確的代碼,但現有的代碼是錯誤的原因是這樣的:
T Stack<T>::pop()
{
T *n = new T; // allocates dynamic memory
*n = myStack.front(); // reference to T from front() copied to allocated T object
myStack.pop_front(); // removes the T in the stack
return *n; // copies your allocated T object to the return value
// your pointer variable goes out of scope, that address is stored nowhere,
// this is where the leak occurs...
}
T * N =新款T; 你正在使用new創建T而不使用它。那就是問題所在。
複製語義是C++的最大優勢之一,因爲你可以把編譯器和類型'T'的作者指責:
T Stack<T>::pop() // may throw
{
T ret = myStack.front();
myStack.pop_front();
return ret;
}
但請注意,這是一個子理想形態一個流行功能。複製後,可能會拋出異常,這使得實現一個異常安全的彈出功能基本上是不可能的。
容器std::stack<>
解決了通過使返回類型void
:
void Stack<T>::pop() // no-throw [if T is written by a sane coder]
{
myStack.pop_front();
}
T Stack<T>::back() // may throw
{
return myStack.front();
}
這爲您提供了一個平均值來清理在破壞你的籌碼沒有拋出異常(在C投擲析構函數++是,按照慣例(不標準),禁止)。
我實際上已經嘗試過這種方法,但當時並不奏效。可能是粗心大意和錯誤的東西。儘管工作,但感謝大家的幫助! – user1740222
請注意,如果移動構造「T」是一個無投擲操作,則這只是強烈異常安全的。如果它可以拋出(或者'T'只有一個拋出的複製構造函數),那麼如果複製到返回值失敗,則可能會丟失'T'中的數據。如果你希望這個操作是無拋出的(對於合理的'T'),那麼把第一行改成'T n {std :: move(myStack.front())};' – Mankarse