既然打算把unique_ptr寫一個系列,就要詳盡一點,有些內容也許在vector的時候有個涉及,但是現在還是再談論一番。
我們要把unique_ptr看做一個類,廢話了,它當然是一個類。所以這個類肯定也重載了賦值運算符,即operator=。現在就開始看看operator=在unique_ptr中的使用:
官方描述如下:
move assignment (1)
unique_ptr& operator= (unique_ptr&& x) noexcept;
assign null pointer (2)
unique_ptr& operator= (nullptr_t) noexcept;
type-cast assignment (3)
template
unique_ptr& operator= (unique_ptr&& x) noexcept;
copy assignment (deleted!) (4)
unique_ptr& operator= (const unique_ptr&) = delete;
這裡簡要實例:
#include
#include
int main () {
std::unique_ptr foo;
std::unique_ptr bar;
foo = std::unique_ptr(new int (101)); // rvalue
bar = std::move(foo); // using std::move
std::cout << "foo: ";
if (foo) std::cout << *foo << '\n'; else std::cout << "empty\n";
std::cout << "bar: ";
if (bar) std::cout << *bar << '\n'; else std::cout << "empty\n";
return 0;
}
輸出:
foo: empty
bar: 101
唯一需要說明的就是std::move後,foo變為了empty,如果對於這個empty再做一些操作的話,就會導致一些災難了。
其實說白了,就是摧毀原來的指針,並把新指針指向原來指針指向的對象。。。。
那麼接下來reset方法即出廠了,到達上面的效果:
#include
#include
int main () {
std::unique_ptr up; // empty
up.reset (new int); // takes ownership of pointer
*up=5;
std::cout << *up << '\n';
up.reset (new int); // deletes managed object, acquires new pointer
*up=10;
std::cout << *up << '\n';
up.reset(); // deletes managed object
return 0;
}
//輸出:
5
10
swap
我們在vector裡就接觸過,unique_ptr同樣具有這個成員函數:
Exchanges the contents of the unique_ptr object with those of x, transferring ownership of any managed object between them without destroying either.
最重要的就是沒有銷毀任何一個:
#include
#include
int main () {
std::unique_ptr foo (new int(10));
std::unique_ptr bar (new int(20));
foo.swap(bar);
std::cout << "foo: " << *foo << '\n';
std::cout << "bar: " << *bar << '\n';
return 0;
}
//輸出
foo為20
bar為10
get
get很簡單,唯一需要注意的就是:
Notice that a call to this function does not make unique_ptr release ownership of the pointer (i.e., it is still responsible for deleting the managed data at some point). Therefore, the value returned by this function shall not be used to construct a new managed pointer.
最主要的一點就是,智能指針沒有釋放,即沒有失去所有權:
#include
#include
int main () {
// foo bar p
// --- --- ---
std::unique_ptr foo; // null
std::unique_ptr bar; // null null
int* p = nullptr; // null null null
foo = std::unique_ptr(new int(10)); // (10) null null
bar = std::move(foo); // null (10) null
p = bar.get(); // null (10) (10)
*p = 20; // null (20) (20)
p = nullptr; // null (20) null
foo = std::unique_ptr(new int(30)); // (30) (20) null
p = foo.release(); // null (20) (30)
*p = 40; // null (20) (40)
std::cout << "foo: ";
if (foo) std::cout << *foo << '\n'; else std::cout << "(null)\n";
std::cout << "bar: ";
if (bar) std::cout << *bar << '\n'; else std::cout << "(null)\n";
std::cout << "p: ";
if (p) std::cout << *p << '\n'; else std::cout << "(null)\n";
std::cout << '\n';
delete p; // the program is now responsible of deleting the object pointed to by p
// bar deletes its managed object automatically
return 0;
}
即上面代碼提到的,p = bar.get(); 後,bar並非被釋放,也就相當於指針p和智能指針bar共同管理一個對象,所以就*p做的一切,都會反應到bar指向的對象上。
這段代碼有了一個與get相對比的方法:release
release
不必多說:
This call does not destroy the managed object, but the unique_ptr object is released from the responsibility of deleting the object. Some other entity must take responsibility for deleting the object at some point.
重點就是一句話:智能指針被釋放。
#include
#include
int main () {
std::unique_ptr auto_pointer (new int);
int * manual_pointer;
*auto_pointer=10;
manual_pointer = auto_pointer.release();
// (auto_pointer is now empty)
std::cout << "manual_pointer points to " << *manual_pointer << '\n';
delete manual_pointer;
return 0;
}
最後了,再介紹一個operator bool吧,即unique_ptr有這樣一個成員函數,來檢查是否為空:
#include
#include
int main () {
std::unique_ptr foo;
std::unique_ptr bar (new int(12));
if (foo) std::cout << "foo points to " << *foo << '\n';
else std::cout << "foo is empty\n";
if (bar) std::cout << "bar points to " << *bar << '\n';
else std::cout << "bar is empty\n";
return 0;
}