std::shared_ptr
首先來介紹shared_ptr,包含在memory頭文件中,它的存在,使得更容易也更安全地使用動態內存。
智能指針也是模板,常用其初始化方式有以下幾種。初始化方式:
1)默認初始化方式。
std::shared_ptr<std::string> p1; // 指向空string
std::shared_ptr<std::list<int>> p2; // 指向int的list
2)使用make_shared函數模板,make_shared聲明如下:(推薦)
template <class T, class... Args>
shared_ptr<T> make_shared (Args&&... args);
從聲明可以看出其用法,必須指定想要創建的對象的類型,例如:
// 指向一個值爲3的int的shared_ptr
std::shared_ptr<int> p3 = std::make_shared<int>(3);
// 指向值爲"9999"的string
std::shared_ptr<std::string> p4 = std::make_shared<std::string>(4, '9');
// 更簡潔的方式,使用auto保存返回結果,構造一個指向空vector<std::string>
auto p5 = std::make_shared<std::vector<std::string>>();
表示使用括號內參數來構造給定的類型對象。
3) 結合new,直接初始化形式
std::shared_ptr<int> p2(new int(4)); // 必須顯示初始化,不支持隱式轉換。
shared_ptr會根據其所指向的對象的引用計數是否爲0來決定是否銷燬該對象,,並釋放所佔用的內存。注意不要混合使用普通指針和智能指針,若將一個智能指針綁定到一個普通指針時,我們就把內存的責任交給share_ptr來處理,就不要再使用普通指針來訪問內存了。
4) reset方式
std::shared_ptr<int> sp2;
sp2.reset(new int(3));
std::weak_ptr
std::weak是對對象的弱引用,是一種不控制對象生存期的指針,只是用於訪問對象,通俗地說就是當沒有shared_ptr之類指針指向對象時,即使有weak_ptr指向對象,對象依然會被釋放。
初始化代碼示例:
#include <iostream>
#include <memory>
int main ()
{
// 構建一個shared_ptr
auto sp = std::make_shared<int>(42);
std::cout << "sp use count is " << sp.use_count() << std::endl;
// 方式1 通過構造函數初始化
std::weak_ptr<int> wp1(sp);
std::cout << "sp use count is " << sp.use_count() << std::endl;
// 方式2 通過拷貝構造函數來初始化
std::weak_ptr<int> wp2(wp1);
std::cout << "sp use count is " << sp.use_count() << std::endl;
// 方式3 通過weak_ptr來賦值初始化
std::weak_ptr<int> wp3;
wp2 = wp1;
std::cout << "sp use count is " << sp.use_count() << std::endl;
// std::weak_ptr 訪問對象的方式舉例
if (!wp2.expired())
{
if (auto np2 = wp2.lock())
{
std::cout << "-----np2 point to value is " << *np2 << std::endl;
}
}
sp.reset();
if (wp2.expired())
{
std::cout << "obj has been dectruct." << std::endl;
}
else
{
if (auto np2 = wp2.lock())
{
std::cout << "====np2 point to value is " << *np2 << std::endl;
}
}
return 0;
}
輸出信息如下:
sp use count is 1
sp use count is 1
sp use count is 1
sp use count is 1
-----np2 point to value is 42
obj has been dectruct.
std::weak_ptr因爲不管理對象的生命週期,所以它一般適用於那些資源對象,能用就用,如果已經銷燬了就不用的使用場景。
std::unique_ptr指針
一個unique_ptr “擁有”它所指向的對象,任意時刻只能有一個unique_ptr指針指向一個給定的對象。unique_ptr的初始化方式如下:
#include <iostream>
#include <memory>
int main ()
{
// 方式1 使用默認構造函數
std::unique_ptr<double> up1;
// 方式2 通過內置指針構造
std::unique_ptr<double> up3(new double(9.9));
std::cout << "up3 point to value: " << *up3 << std::endl;
// 方式3 使用reset
std::unique_ptr<double> up4;
up4.reset(new double(8.8));
std::cout << "up4 point to value: " << *up4 << std::endl;
// 方式4 使用make_unique c++14才支持
std::unique_ptr<double> up5 = std::make_unique<double>(7.7);
std::cout << "up5 point to value: " << *up5 << std::endl;
return 0;
}
release結合reset的unique_ptr的用法
#include <iostream>
#include <memory>
int main ()
{
std::unique_ptr<int> up1(new int(1));
std::cout << "up1 point to value: " << *up1 << std::endl;
// release 放棄對指針的控制權,返回指針並將up1置空
std::unique_ptr<int> up2(up1.release());
std::cout << "up2 point to value: " << *up2 << std::endl;
std::unique_ptr<int> up3(new int(3));
// 將所有權從up2轉移到up3
up3.reset(up2.release());
std::cout << "up3 point to value: " << *up3 << std::endl;
std::unique_ptr<int> up4 = std::make_unique<int>(4);
//up4.release(); // 錯誤寫法:up4不會釋放內存,且丟失了其之前所指向對象的指針
std::cout << "up4 point to value: " << *up4 << std::endl;
auto p = up4.release(); // 正確寫法:需要記錄返回的指針且記得delete p 操作
delete p;
std::cout << "hello world" << std::endl;
return 0;
}
輸出信息如下:
up1 point to value: 1
up2 point to value: 1
up3 point to value: 1
up4 point to value: 4
hello world
std::unique_ptr移動構造
#include <iostream>
#include <memory>
// std::unique_ptr 不支持copy 構造和 copy賦值
int main ()
{
std::unique_ptr<int> up1 = std::make_unique<int>(1);
std::unique_ptr<int> up2(std::move(up1));
std::unique_ptr<int> up3;
up3 = std::move(up2);
std::cout << "up3 point to value: " << *up3 << std::endl;
return 0;
}
好了,以上都是比較基本的用法,暫且寫這麼多。