十三、指針和引用(三) 1、std::unique_ptr(唯一智能指針) 1)概念 std::unique_ptr是所謂的智能指針的一種,主要目的是為瞭解決原生指針安全性不足的弊端 //std::unique_ptr指針的聲明語法 std::unqiue_ptr<類型>變數名稱{}; //示例 s ...
十三、指針和引用(三)
1、std::unique_ptr(唯一智能指針)
1)概念
std::unique_ptr是所謂的智能指針的一種,主要目的是為瞭解決原生指針安全性不足的弊端
//std::unique_ptr指針的聲明語法
std::unqiue_ptr<類型>變數名稱{};
//示例
std::unique_ptr<int>ptrA{std::make_unique<int>(150)}; // 申請一個具有1個int類型大小的指針,值為150
std::cout<<*ptrA; //指針使用
std::unique_ptr<int[]>ptrB{new int[5]}; //C++14之前的寫法,申請一個具有5個int類型大小的指針
std::unique_ptr<int[]>ptrB{std::make_unique<int[]>(10)}; //申請一個具有5個int類型大小的指針
ptrB[0]=250; //指針使用,此聲明方法,只能通過數組訪問
2)唯一智能指針特性
std::unique_ptr的特點是該指針具有唯一性,因此無法讓兩個std::unique_ptr指針存放相同的記憶體地址,如下:
std::unique_ptr<int>ptrA{std::make_unique<int>(150)};
std::unique_ptr<int>ptrB{};
//ptrA=ptrB; //錯誤,無法直接賦值
#include <iostream>
int main()
{
int* a = new int[5];
std::unique_ptr<int[]>intptr{ std::make_unique<int[]>(5) }; //申請一個具有5個int類型大小的指針
std::unique_ptr<int>intptrA{ std::make_unique<int>(5) }; // 申請一個具有1個int類型大小的指針,值為5
std::cout << intptr << " " << intptr[0]<<std::endl; //013D5C98 0
std::cout << intptrA << " " << *intptrA << std::endl; //013DEC10 5
}
3)reset()用法
reset將會釋放std::unique_ptr的記憶體空間,並且將std::unique_ptr設置為nullptr;
//reset()用法示例
std::unique_ptr<int>ptrA{std::make_unique<int>(150)};
ptrA.reset(); //此時ptrA的記憶體空間被釋放,ptrA的值設置成了nullptr
//reset()示例
#include <iostream>
int main()
{
int* a = new int[5];
delete[] a; //釋放new申請的記憶體空間
std::unique_ptr<int>ptrA{ std::make_unique<int>(100) };
std::cout << "釋放記憶體前的地址:"<<ptrA << std::endl;
ptrA.reset(); //釋放唯一智能指針
std::cout << "釋放記憶體後的地址:" << ptrA << std::endl;
}
4)get()用法:返回一個std::unique_ptr的指針
//get()用法
std::unique_ptr<int>ptrA{std::make_unique<int>(150)};
int*p = ptrA.get(); //相當於將ptrA申請時的記憶體賦值給p
5)release()用法
relsease將會返回std::unique_ptr的指針,並且將std::unique_ptr設置為nullptr,但是註意release並不會釋放其占用的記憶體空間
//relseae()用法
std::unique_ptr<int>ptrA{std::make_unique<int>(150)};
int* p = ptrA.release();
//此時ptrA占用的記憶體空間沒有被釋放,ptrA的值設置成了nullptr,p等於ptrA申請記憶體時的地址
//release只是將申請的記憶體地址設置為了0,並沒有釋放,並且將原理的地址進行了返回
#include <iostream>
int main()
{
int* a = new int[5];
std::unique_ptr<int>ptrA{ std::make_unique<int>(100) };
std::cout << "release前的地址:" << ptrA << std::endl;
a = ptrA.release();
std::cout << "release後的地址:" << ptrA << std::endl;
std::cout << "a的地址:" << a << std::endl;
}
6)唯一智能指針的轉移(move)
std::unique_ptr指針因為具有唯一性,因此不能被覆制,但是可以轉移
//唯一智能指針轉移語法
轉移後的指針變數=std::move(轉移前的指針變數);
//示例
std::unique_ptr<int>ptrA{std::make_unique<int>(150)};
std::unique_ptr<int>ptrB;
ptrB=std::move(ptrA); //將ptrA的地址轉移到ptrB,轉移後ptrA被設置為nullptr
2、std::shared_per(共用智能指針)
1)共用智能指針語法
//共用智能指針語法
std::shared_ptr<類型>變數名稱{};
//示例
std::shared_ptr<int>ptrA{};
std::shared_ptr<int>ptrB{std::make_shared<int>(5)};
//註:std::make_shared不支持新式的數組的定義方式,只能通過new的方式
std::shared_ptr<int[]>ptr{new int[5]{1,2,3,4,5}};
//共用智能指針的定義及使用
#include <iostream>
int main()
{
int* a{};
std::shared_ptr<int>ptrA{ std::make_shared<int>(5) };
std::shared_ptr<int>ptrB{ ptrA }; //共用ptrA的記憶體地址
std::shared_ptr<int>ptrC{ ptrA };
std::cout << "ptrA的記憶體地址為:" << ptrA << std::endl;
std::cout << "ptrB的記憶體地址為:" << ptrB << std::endl;
std::cout << "ptrA的記憶體地址為:" << ptrC << std::endl;
std::cout << "\n";
std::cout << "ptrA的值為:" << *ptrA << std::endl;
std::cout << "ptrB的值為:" << *ptrB << std::endl;
}
2)共用智能指針特性
可以有多個std::shared_ptr指向同一地址,同一地址下只有當最後一個std::shared_ptr釋放的時候,才會釋放其占用的記憶體空間,std::shared_ptr會記錄當前地址有多少個智能指針調用
3)統計共用指針當前有多少個對象調用(use_count)
//統計共用指針當前有多少個對象調用
long std::shared_ptr.use_count();
.user_count(); //會返回當前指針共有多少個對象調用
//use.count()用法示例
#include <iostream>
int main()
{
int* a{};
std::shared_ptr<int>ptrA{ std::make_shared<int>(5) };
std::shared_ptr<int>ptrB{ ptrA }; //共用ptrA的記憶體地址
std::shared_ptr<int>ptrC{ ptrA };
std::cout << "ptrA指針共有多少個指針調用:" << ptrA.use_count() << std::endl;
}
5)判斷共用智能指針是否唯一(unique)
//判斷共用智能指針是否唯一
bool std::shared_ptr.unique();
//unique()返回一個bool值,如果當前智能指針是唯一擁有該指針的,那麼返回true,負責返回false
註:C++17標準無法使用該函數,只能在17之前使用
//unique()用法
#include <iostream>
int main()
{
int* a{};
std::shared_ptr<int>ptrA{ std::make_shared<int>(5) };
std::cout << "判斷指針指針ptrA是否唯一:" << ptrA.unique() << std::endl;
std::shared_ptr<int>ptrB{ ptrA }; //共用ptrA的記憶體地址
std::shared_ptr<int>ptrC{ ptrA };
std::cout << "判斷指針指針ptrA是否唯一:" << ptrA.unique() << std::endl;
}
4)共用智能指針的釋放
reset()會將當前共用指針設置為nullptr,同時如果當前智能指針是最後一個擁有該指針的對象,那麼將會釋放記憶體。只有最後一個指針變數釋放,才能釋放記憶體空間
//共用智能指針的釋放
std::shared_ptr.reset();
//reset()使用
#include <iostream>
int main()
{
int* a{};
std::shared_ptr<int>ptrA{ std::make_shared<int>(5) };
std::shared_ptr<int>ptrB{ ptrA }; //共用ptrA的記憶體地址
std::shared_ptr<int>ptrC{ ptrA };
ptrB.reset(); //只是修改指針的指向,並不釋放指針記憶體地址
std::cout << ptrB << std::endl;
ptrA.reset();
std::cout << ptrA << std::endl;
std::cout << ptrC << std::endl;
ptrC.reset(); //釋放智能指針的記憶體地址
std::cout << ptrC << std::endl;
}