C++智能指针:unique_ptr详解
生活随笔
收集整理的這篇文章主要介紹了
C++智能指针:unique_ptr详解
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- unique_ptr描述
- 聲明
- 作用
- 函數指針描述
- 總結
unique_ptr描述
聲明
頭文件:<memory>
模版類:
- 默認類型
template <class T, class D = default_delete<T>> class unique_ptr - 數組類型
template <class T, class D> class unique_ptr<T[],D>;
作用
與shared_ptr最大的區別即是unique_ptr不能夠共享同一個地址,它對地址是獨占得。當unique_ptr對象的生命周期結束,則它所引用的地址空間也會被釋放。
一個unique_ptr對象主要包含兩個部分
- 一個存儲指針:主要用來管理對象的地址空間。它是在構造函數中分配的地址,并且能夠通過賦值運算符以及reset成員函數進行地址空間的重新指向。并且可以通過get和release成員變量進行單獨訪問,獲取unique_ptr對象的地址空間。
- 一個存儲刪除器:刪除器為一個可以被調用的對象。主要被用來刪除unique_ptr對象的地址空間。同時能夠使用賦值運算符進行當前對象的更改,并通過get_deleter成員函數進行單獨訪問。
函數指針描述
- 構造函數
輸出如下://unique_ptr constructor example #include <iostream> #include <memory>int main () {std::default_delete<int> d;//默認為空std::unique_ptr<int> u1;//使用null初始化指針,仍然為空std::unique_ptr<int> u2 (nullptr);//正常初始化std::unique_ptr<int> u3 (new int);//存儲指針正常初始化,之后并初始化刪除器的值,所以不為空std::unique_ptr<int> u4 (new int, d);//存儲指針正常初始化,之后刪除器使用默認的構造函數進行初始化,所以unique_ptr又為空了std::unique_ptr<int> u5 (new int, std::default_delete<int>());std::unique_ptr<int> u6 (std::move(u5));std::unique_ptr<int> u7 (std::move(u6));std::unique_ptr<int> u8 (std::auto_ptr<int>(new int));std::cout << "u1: " << (u1?"not null":"null") << '\n';std::cout << "u2: " << (u2?"not null":"null") << '\n';std::cout << "u3: " << (u3?"not null":"null") << '\n';std::cout << "u4: " << (u4?"not null":"null") << '\n';std::cout << "u5: " << (u5?"not null":"null") << '\n';std::cout << "u6: " << (u6?"not null":"null") << '\n';std::cout << "u7: " << (u7?"not null":"null") << '\n';std::cout << "u8: " << (u8?"not null":"null") << '\n';return 0; }u1: null u2: null u3: not null u4: not null u5: null u6: null u7: not null u8: not null - 析構函數;如果對象為空的unique_ptr,即使用get()==nullptr,則析構函數無法產生作用
否則會正常刪除對象,就像get_deleter()函數一樣
輸出如下:// unique_ptr destructor example #include <iostream> #include <memory>int main () {auto deleter = [](int*p){delete p;std::cout << "[deleter called]\n";};std::unique_ptr<int,decltype(deleter)> foo (new int,deleter);std::cout << "foo " << (foo?"is not":"is") << " empty\n";return 0; // [deleter called] }foo is not empty [deleter called] operator=
輸出如下:// unique_ptr::operator= example #include <iostream> #include <memory>int main () {std::unique_ptr<int> foo;std::unique_ptr<int> bar;foo = std::unique_ptr<int>(new int (101)); // rvalue//std::move操作是將foo對象的地址以及空間內容轉給bar,所以執行之后foo變為了empty//之所以使用std::move操作是因為unique_ptr對象地址空間只能被一個對象獨享bar = std::move(foo); // using std::movestd::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: 101std :: unique_ptr :: get成員,改成員函數返回被管理的unique_ptr對象,此函數的調用不會使unique_ptr釋放指針的所有權(即,它仍然負責在某個時刻刪除管理數據)。因此,此函數返回的值不得用于構造新的管理指針。為了活動存儲指針,并且能夠正常釋放,則使用release()成員函數
輸出如下:// unique_ptr::get vs unique_ptr::release #include <iostream> #include <memory>int main () {// foo bar p// --- --- ---std::unique_ptr<int> foo; // nullstd::unique_ptr<int> bar; // null nullint* p = nullptr; // null null nullfoo = std::unique_ptr<int>(new int(10)); // (10) null null//這里經過std::move之后foo的地址以及內容轉移給了barstd::cout << "foo: " << foo.get() << std::endl;bar = std::move(foo); // null (10) nullstd::cout << "foo: " << foo.get() << std::endl;std::cout << "bar: " << bar.get() << std::endl;p = bar.get(); // null (10) (10)*p = 20; // null (20) (20)p = nullptr; // null (20) nullfoo = std::unique_ptr<int>(new int(30)); // (30) (20) nullp = 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 automaticallyreturn 0; }optionscompilationexecution foo: 0x817a10 foo: 0 bar: 0x817a10 foo: (null) bar: 20 p: 40std :: unique_ptr :: release
通過改成員函數的返回值以及空指針來釋放當前unique_ptr指針的所有權
當前調用并不會破壞管理對象,改成員函數不會刪除對象,而需要其他實體在某個時候刪除對象。如果想要強制刪除對象,需要使用reset或者賦值運算符(std::move)
輸出如下:// unique_ptr::release example #include <iostream> #include <memory>int main () {std::unique_ptr<int> auto_pointer (new int);int * manual_pointer;*auto_pointer=10;std::cout << " auto_pointer " << auto_pointer.get() << std::endl;manual_pointer = auto_pointer.release();std::cout << " auto_pointer " << auto_pointer.get() << std::endl;std::cout << " manual_pointer " << manual_pointer<< std::endl;// (auto_pointer is now empty)std::cout << "manual_pointer points to " << *manual_pointer << '\n';delete manual_pointer;return 0; }auto_pointer 0x3afffa0auto_pointer 0manual_pointer 0x3afffa0 manual_pointer points to 10std::unique_ptr::reset
void reset (pointer p = pointer()) noexcept;
破壞掉當前unique_ptr對象,并且獲取它所有權p,如果p是空的,則當前unique_ptr對象也即為空
如果想要釋放當前對象,并且并不破壞對象所指地址空間以及內容,則使用release成員函數
輸出如下:// unique_ptr::reset example #include <iostream> #include <memory>int main () {std::unique_ptr<int> up; // empty//reset之后 up之前對象所指空間已經被破壞,并重新接管up對象,分配新的地址空間up.reset (new int); // takes ownership of pointer//可以看到地址空間已經由之前的null變為重新分配的空間std::cout << *up << " " << up.get() << '\n';*up=5;std::cout << *up << " " << up.get() << '\n';up.reset (new int); // deletes managed object, acquires new pointer*up=10;std::cout << *up << " " << up.get() << '\n';up.reset(); // deletes managed objectreturn 0; }0 0xd7dc70 5 0xd7dc70 10 0xd7dc90std::unique_ptr::swap交換對象空間以及內容,且并不破壞地址空間
輸出如下:// unique_ptr::swap example#include <iostream>#include <memory>int main () {std::unique_ptr<int> foo (new int(10));std::unique_ptr<int> bar (new int(20));std::cout << "foo: " << *foo << " " << foo.get() << '\n';std::cout << "bar: " << *bar << " " << bar.get() << '\n';foo.swap(bar);std::cout << "foo: " << *foo << " " << foo.get() << '\n';std::cout << "bar: " << *bar << " " << bar.get() << '\n';return 0;}foo: 10 0x2cd9ae0 bar: 20 0x2cd9b00 foo: 20 0x2cd9b00 bar: 10 0x2cd9ae0
總結
- shared_ptr地址空間無法被多個智能指針共享,當實際當前對象地址作用域結束,則改對象所占有地址空間將被釋放
- 使用release成員函數可以轉移unique_ptr隊形的所有圈,即將unique_ptr對象轉為非unique_ptr對象,并不破壞地址
- 使用
reset會重置對象地址空間,并重新分配。會破壞地址空間 - 使用賦值元算符,和reset函數類似重新指定地址空間,同樣會破壞地址空間
- unique_ptr對象的返回智能使用成員函數
get
總結
以上是生活随笔為你收集整理的C++智能指针:unique_ptr详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大家感觉万圣节小炮的皮肤怎么样
- 下一篇: 亏赚???有女帝