據我所知,unique_ptr
是某個對象的單一所有者,當它超出範圍時,它會釋放該對象。我不明白的是以下情況:重定向unique_ptr時會發生什麼?
unique_ptr<int> p(new int(1));
p = unique_ptr<int>(new int(2));
new int(1)
如果p
被重定向到另一個存儲位置new int(2)
(因爲p
只能擁有其中的一個)與第一對象會發生什麼?
據我所知,unique_ptr
是某個對象的單一所有者,當它超出範圍時,它會釋放該對象。我不明白的是以下情況:重定向unique_ptr時會發生什麼?
unique_ptr<int> p(new int(1));
p = unique_ptr<int>(new int(2));
new int(1)
如果p
被重定向到另一個存儲位置new int(2)
(因爲p
只能擁有其中的一個)與第一對象會發生什麼?
unique_ptr
破壞它擁有當unique_ptr
是銷燬對象編號或重新編號爲。例如:
#include <iostream>
#include <memory>
using namespace std;
struct T {
T(int x) : x(x) {
cout << "T(" << x << ")\n";
}
~T() {
cout << "~T(" << x << ")\n";
}
int x;
};
int main() {
unique_ptr<T> p(new T(1));
p = unique_ptr<T>(new T(2));
}
這將打印:
T(1)
創建所述第一對象時。T(2)
當第二個對象被創建時。~T(1)
當第一個對象被賦值運算符p
釋放時。~T(2)
當第二個對象被p
的析構函數釋放時。unique_ptr
被定義爲確保第一個int被正確解除分配,因此它會調用delete
,釋放保留的內存。
這是這段代碼有點相同:
int* p = new int(1);
delete p;
p = new int(2);
會發生什麼事了詳細是這樣的:
new int(1)
一個新的整數。p
的剛創建的實例unique_ptr
。這是一個剛剛存儲指針的對象。new int(2)
創建第二個int。unique_ptr<int>(new int(2))
將此指針傳遞給新的unique_ptr
,這是unique_ptr的臨時實例(我們將在第二秒看到原因)並將指針存儲到第二個int中。p
。現在賦值運算符被定義爲刪除先前擁有的對象(第一個int)並獲取被賦值的unique_ptr(第二個int)擁有的對象的所有權。一個實現如下所示。此時p
擁有第二個int,第一個int被刪除,臨時不擁有對象(持有nullptr
)。unique_ptr
超出了範圍,因爲我們從未給它命名或存儲對它的引用,所以它的析構函數被調用。但它只能保持nullptr
。因此,使用原始指針更詳細相當於將是這樣的:
int* p = new int(1); //create an int
{
int* tmp = new int(2); //create second int
int* del = p; //we need to delete this (first int)
//take ownership of the temporary (second int)
p = tmp;
tmp=nullptr;
//delete the old object (first int)
delete del;
} //tmp and del go out of scope here, but tmp holds the nullptr and del is deleted
//first int is deleted, p points to the second int here
編輯示蹤劑: 這是由Visual Studio所使用的實現(註釋是<memory>
一部分井):
typedef unique_ptr<_Ty> _Myt;
_Myt& operator=(_Myt&& _Right) _NOEXCEPT
{ // assign by moving _Right
if (this != &_Right)
{ // different, do the move
reset(_Right.release());
this->get_deleter() = _STD forward<_Dx>(_Right.get_deleter());
}
return (*this);
}
void reset(pointer _Ptr = pointer()) _NOEXCEPT
{ // establish new pointer
pointer _Old = get();
this->_Myptr() = _Ptr;
if (_Old != pointer())
this->get_deleter()(_Old);
}
它消失了,永遠消失了,但保證能夠正確清理。如果類型不是POD,它的析構函數將被調用(除非使用了一些自定義釋放器)。 – Tas
這就是我不明白的地方。誰會把他清理乾淨,因爲他不是沒有人擁有的? – Tracer
'unique_ptr'是一個像其他任何對象一樣的構造函數和析構函數。當調用'p = unique_ptr'時,將調用'p'的析構函數來清理內存。 – Tas