面試之快速學習C++11-完美轉發,nullptr, shared_ptr,unique_ptr,weak_ptr,shared_from_this

完美轉發及其實現

  1. 函數模版可以將自己的參數完美地轉發給內部調用的其他函數。所謂完美,即不僅能準確地轉發參數的值,還能保證被轉發參數的左右值屬性不變
  2. 引用折疊:如果任一引用為左值引用,則結果為左值引用,否則為右值引用。
& && -> &
&& & -> &
& & -> &
&& && -> &&
void actualRun(int a) {}
template <typename T>
void testPerfectForward(T &&param) {actualRun(param);
}void testPerfectForwardMain() {int a = 0;testPerfectForward(a);
}

上述 T 為int &。 那么整個為 int & &&-> int &

回到完美轉發,假設現在我需要轉發a,那么注意一下實現完美轉發需要這樣寫


template <typename T>
void testPerfectForward1(T &&param) {actualRun(std::forward(param));
}

forward大致實現原理
static_cast + &&

template <typename T>
T&& forwad(T &param) {return static_cast<T&&>(param);
}

注意其實std::move底層實現也是 static_cast

C++11 nullptr:初始化空指針

  1. #define NULL 0
#include <iostream>
using namespace std;void isnull(void *c){cout << "void*c" << endl;
}
void isnull(int n){cout << "int n" << endl;
}
void testNull1() {isnull(0);//isnull(NULL);//Call to 'isnull' is ambiguousisnull((void*)NULL);/*int nvoid*c*/
}

1 . nullptr 是 nullptr_t 類型的右值常量,專用于初始化空類型指針。nullptr_t 是 C++11 新增加的數據類型,可稱為“指針空值類型”。也就是說,nullpter 僅是該類型的一個實例對象(已經定義好,可以直接使用),如果需要我們完全定義出多個同 nullptr 完全一樣的實例對象。

  1. nullptr 可以被隱式轉換成任意的指針類型。故如下:

void testNull2() {isnull(0);//isnull(NULL);//Call to 'isnull' is ambiguousisnull((void*)NULL);isnull(nullptr);/*int nvoid*cvoid*c*/}
  1. 借助執行結果不難看出,由于 nullptr 無法隱式轉換為整形,而可以隱式匹配指針類型,因此執行結果和我們的預期相符
void testNullMain() {
//    int *p = 0;
//    int *q = NULL;
//    testNull1(0);
//    testNull1(NULL);
}

.C++11 shared_ptr智能指針

void deleteInt(int *p) {delete []p;
}
void testSharedPtr () {std::cout << "testSharePtr: " << endl;//初始化空的shareptr,引用計數為0不是1std::shared_ptr<int> p1;std::shared_ptr<int> p2(nullptr);std::shared_ptr<int> p3(new int(10));std::shared_ptr<int> p4 = std::make_shared<int>(10);//調用拷貝構造函數std::shared_ptr<int> p5(p4);  //或者 p4  = p3;//調用移動構造函數std::shared_ptr<int> p6(std::move(p4)); //或者p6 = std::move(p4)//智能指針可以拷貝,給多個智能指針用,引用計數+1,但是普通指針,只能拷貝給一個智能指針int *p = new int(1);std::shared_ptr<int> pp1(p);
//    std::shared_ptr<int> pp2(p); //錯誤!!!!// 在初始化 shared_ptr 智能指針時,還可以自定義所指堆內存的釋放規則,這樣當堆內存的引用計數為 0 時,會優先調用我們自定義的釋放規則。在某些場景中,自定義釋放規則是很有必要的,比如,對于申請的動態數組來說,share—_ptr指針默認的釋放規則是不支持釋放數組的,值呢個自定義對于的釋放規則,如下://釋放規則可以使用 C++11 標準中提供的 default_delete<T> 模板類,我們也可以自定義釋放規則:std::shared_ptr<int> p10(new int[10], std::default_delete<int[]>());std::shared_ptr<int> p11(new int[10], deleteInt);std::shared_ptr<int> p12(new int[10], [](int *p){delete []p;});std::shared_ptr<int> ppp1 = std::make_shared<int>(10);std::shared_ptr<int> ppp2(ppp1);std::cout << *ppp2 << endl;cout<< ppp2.use_count()<<endl;ppp1.reset();if (p1) {std::cout << "ppp1 is not null !"<< endl;} else {std::cout << "ppp1 is null !"<< endl;}std::cout << *ppp2 << endl;cout<< ppp2.use_count()<<endl;
}
1 shared_ptr<T>模板類常用成員方法成員方法名    功 能operator=()    重載賦值號,使得同一類型的 shared_ptr 智能指針可以相互賦值。operator*()    重載 * 號,獲取當前 shared_ptr 智能指針對象指向的數據。operator->()    重載 -> 號,當智能指針指向的數據類型為自定義的結構體時,通過 -> 運算符可以獲取其內部的指定成員。swap()    交換 2 個相同類型 shared_ptr 智能指針的內容。reset()    當函數沒有實參時,該函數會使當前 shared_ptr 所指堆內存的引用計數減 1,同時將當前對象重置為一個空指針;當為函數傳遞一個新申請的堆內存時,則調用該函數的 shared_ptr 對象會獲得該存儲空間的所有權,并且引用計數的初始值為 1get()    獲得 shared_ptr 對象內部包含的普通指針。use_count()    返回同當前 shared_ptr 對象(包括它)指向相同的所有 shared_ptr 對象的數量。unique()    判斷當前 shared_ptr 對象指向的堆內存,是否不再有其它 shared_ptr 對象再指向它。operator bool()    判斷當前 shared_ptr 對象是否為空智能指針,如果是空指針,返回 false;反之,返回 true。*/

C++11 unique_ptr智能指針

unique_ptr 指針指向的堆內存無法同其它 unique_ptr 共享,也就是說,每個 unique_ptr 指針都獨自擁有對其所指堆內存空間的所有權

void testUniqueptr() {std::unique_ptr<int> p1(new int(3));
//    std::unique_ptr<int> p1(p2);std::unique_ptr<int> p2(std::move(p1));// 默認情況下,unique_ptr 指針采用 std::default_delete<T> 方法釋放堆內存。當然,我們也可以自定義符合實際場景的釋放規則。值得一提的是,和 shared_ptr 指針不同,為 unique_ptr 自定義釋放規則,只能采用函數對象的方式。例如:struct myDel {void operator()(int *p) {delete p;}};std::unique_ptr<int, myDel> p7(new int);
//    std::unique_ptr<int, myDel> p6(new int);std::unique_ptr<int> p10(new int);*p10 = 10;//p10釋放當前所指堆的所有權, 但該存儲空間不會被銷毀,轉移給了pint *p = p10.release();std::unique_ptr<int> p11;//中 p 表示一個普通指針,如果 p 為 nullptr,則當前 unique_ptr 也變成空指針;反之,則該函數會釋放當前 unique_ptr 指針指向的堆內存(如果有),然后獲取 p 所指堆內存的所有權(p 為 nullptr)。p11.reset(p);//    int *p2 = p;
}

C++11 weak_ptr智能指針

weak_ptr是為了配合shared_ptr而引入的一種智能指針,它不具有普通指針的行為,沒有重載*和->兩個操作符,它的最大作用在于協助shared_ptr工作,像旁觀者那樣觀測資源的使用情況。
weak_ptr可以從一個shared_ptr或者另一個weak_ptr對象構造,獲得資源的觀測權。但weak_ptr沒有共享資源,它的構造不會引起指針引用計數的增加。
使用weak_ptr的成員函數use_count()可以觀測資源的引用計數,另一個成員函數expired()的功能等價于use_count()==0,但更快,表示被觀測的資源 (也就是shared_ptr的管理的資源)已經不復存在。
weak_ptr可以使用一個非常重要的成員函數lock()從被觀測的shared_ptr 獲得一個可用的shared_ptr對象,從而操作資源。但當expired()==true的時候,lock()函數將返回一個存儲空指針的shared_ptr。

shared_from_this

#include<memory>class Test: public std::enable_shared_from_this<Test>
{public:  Test();~Test();std::shared_ptr<Test> getSharedFromThis(){return shared_from_this();}
}

在什么情況下要使類A繼承enable_share_from_this?

使用場合:當類A被share_ptr管理,且在類A的成員函數里需要把當前類對象作為參數傳給其他函數時,就需要傳遞一個指向自身的share_ptr。

我們就使類A繼承enable_share_from_this,然后通過其成員函數share_from_this()返回當指向自身的share_ptr。

以上有2個疑惑:

1.把當前類對象作為參數傳給其他函數時,為什么要傳遞share_ptr呢?直接傳遞this指針不可以嗎?

一個裸指針傳遞給調用者,誰也不知道調用者會干什么?假如調用者delete了該對象,而share_tr此時還指向該對象。

2.這樣傳遞share_ptr可以嗎?share_ptr

這樣會造成2個非共享的share_ptr指向一個對象,最后造成2次析構該對象。
————————————————
引用鏈接:https://blog.csdn.net/zk3326312/article/details/79108690
http://c.biancheng.net/view/3730.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/38876.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/38876.shtml
英文地址,請注明出處:http://en.pswp.cn/news/38876.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

在阿里云服務器上安裝Microsoft SharePoint 2016流程

本教程阿里云百科分享如何在阿里云ECS上搭建Microsoft SharePoint 2016。Microsoft SharePoint是Microsoft SharePoint Portal Server的簡稱。SharePoint Portal Server是一個門戶站點&#xff0c;使得企業能夠開發出智能的門戶站點。 目錄 背景信息 步驟一&#xff1a;添加…

【Leetcode 30天Pandas挑戰】學習記錄 下

題目列表&#xff1a; 數據統計:2082. The Number of Rich Customers1173. Immediate Food Delivery I1907. Count Salary Categories 數據分組1741. Find Total Time Spent by Each Employee511. Game Play Analysis I2356. Number of Unique Subjects Taught by Each Teacher…

無涯教程-Perl - setgrent函數

描述 此功能將枚舉設置(或重置)到組條目集的開頭。該函數應在第一次調用getgrent之前調用。 語法 以下是此函數的簡單語法- setgrent返回值 此函數不返回任何值。 例 以下是顯示其基本用法的示例代碼- #!/usr/bin/perl -wwhile( ($name,$passwd,$gid,$members)getgrent…

ide internal errors【bug】

ide internal errors【bug】 前言版權ide internal errors錯誤產生相關資源解決1解決2 設置虛擬內存最后 前言 2023-8-15 12:36:59 以下內容源自《【bug】》 僅供學習交流使用 版權 禁止其他平臺發布時刪除以下此話 本文首次發布于CSDN平臺 作者是CSDN日星月云 博客主頁是h…

C++模板的分離編譯問題

本文主要是了解一下為什么模板的定義和聲明不能分開&#xff0c;需要簡單了解一下編譯的四個階段。 一、理解編譯大致流程 整個編譯流程分為&#xff1a;預處理、編譯、匯編、鏈接&#xff0c;這里以源文件main.cpp文件為例。 預處理&#xff1a;對源文件進行宏替換、去注釋、…

CentOS8防火墻基礎操作應用

查看防火墻某個端口是否開放 firewall-cmd --query-port80/tcp 開放防火墻端口80 firewall-cmd --zonepublic --add-port80/tcp --permanent 關閉80端口 firewall-cmd --zonepublic --remove-port80/tcp --permanent 配置立即生效firewall-cmd --reload 查看防火墻狀態 s…

代碼隨想錄算法訓練營第58天|動態規劃part15|392.判斷子序列、115.不同的子序列

代碼隨想錄算法訓練營第58天&#xff5c;動態規劃part15&#xff5c;392.判斷子序列、115.不同的子序列 392.判斷子序列 392.判斷子序列 思路&#xff1a; &#xff08;這道題也可以用雙指針的思路來實現&#xff0c;時間復雜度也是O(n)&#xff09; 這道題應該算是編輯距…

[Android 11]使用Android Studio調試系統應用之Settings移植(七):演示用AS編譯錯誤問題

文章目錄 1. 篇頭語2. 系列文章3. AS IDE的配置3.1 AS版本3.2 Gradle JDK 版本4. JDK的下載5. AS演示工程地址6.其他版本JDK導致的錯誤1. 篇頭語 距離2021年開始,系列文章發表已經有近兩年了,依舊有網友反饋一些gitee上演示源碼編譯的一些問題,這里就記錄一下。 2. 系列文章…

uniApp引入vant2

uniApp引入vant2 1、cnpm 下載&#xff1a;cnpm i vantlatest-v2 -S2、main.js文件引入 import Vant from ./node_modules/vant/lib/vant;Vue.use(Vant);3.app.vue中引入vant 樣式文件 import /node_modules/vant/lib/index.css;

tomcat服務七層搭建動態頁面查看

一個服務器多實例復制完成 配置tomcat多實例的環境變量 vim /etc/profile.d/tomcat.sh配置tomcat1和tomcat2的環境變量 進入tomcat1修改配置 測試通信端口是否正常 連接正常 toncat 2 配置修改 修改這三個 端口配置修改完成 修改tomcat1 shudown 分別把啟動文件指向tomcat1…

數據結構--最短路徑 Dijkstra算法

數據結構–最短路徑 Dijkstra算法 Dijkstra算法 計算 b e g i n 點到各個點的最短路 \color{red}計算\ begin\ 點到各個點的最短路 計算 begin 點到各個點的最短路 如果是無向圖&#xff0c;可以先把無向圖轉化成有向圖 我們需要2個數組 final[] &#xff08;標記各頂點是否已…

【ARM 嵌入式 編譯系列 10.1 -- GCC 編譯縮減可執行文件 elf 文件大小】

文章目錄 上篇文章&#xff1a;ARM 嵌入式 編譯系列 10 – GCC 編譯縮減可執行文件 elf 文件大小 接著上篇文章 ARM 嵌入式 編譯系列 10 – GCC 編譯縮減可執行文件 elf 文件大小 的介紹&#xff0c;我們看下如何進一步縮小可執行文件test的大小。上篇文章通過 strip --strip-…

RunnerGo的相比較JMeter優勢,能不能替代?

目前在性能測試領域市場jmeter占有率是非常高的&#xff0c;主要原因是相對比其他性能測試工具使用更簡單&#xff08;開源、易擴展&#xff09;&#xff0c;功能更強大&#xff08;滿足多種協議的接口&#xff09;&#xff0c;但是隨著研發協同的升級&#xff0c;平臺化的性能…

進程的概念和特征

進程的概念和特征 進程的概念進程的特征 進程的概念 在多道程序環境下&#xff0c;允許多個程序并發執行&#xff0c;此時他們將失去封閉性&#xff0c;并具有間斷性及不可再現性的特征。為此引入了進程&#xff08;process&#xff09;的概念&#xff0c;以便更好的描述和控制…

【Java】常用工具——異常

1. try-catch-finnaly try必須和catch或者finally組合使用&#xff1b; public class TryDemoOne {public static void main(String[] args) {Scanner input new Scanner(System.in);System.out.println("輸入第1個整數&#xff1a;");int one input.nextInt();S…

主流的嵌入式微處理器

目前主流的嵌入式微處理器系列有&#xff1a; ARM系列 MIPS系列 PowerPC系列 Super H系列 一、MPC/PPC系列 PowerPC(簡稱PPC),其基本設計源自IBM的POWER.1991年&#xff0c;APPLE(蘋果電腦)、IBM、Motorola&#xff08;摩托羅拉&#xff09;組成的AIM聯盟發展出Power微處理器…

mybatis-plus 根據指定字段 批量 刪除/修改

mybatis-plus 提供了根據id批量更新和修改的方法,這個大家都不陌生 但是當表沒有id的時候怎么辦 方案一: 手寫SQL方案二: 手動獲取SqlSessionTemplate 就是把mybatis plus 干的事自己干了方案三 : 重寫 executeBatch 方法結論: mybatis-plus 提供了根據id批量更新和修改的方法,…

Python jupyter lab 設置

在下載好jupyter lab 后&#xff0c;需要對其進行設置&#xff0c;尤其是遠程服務器的時候&#xff0c;因為根本就是沒有屏幕&#xff0c;也沒有瀏覽器。 新建設置文件 jupyter lab --generate-config設置文件內部參數 vim ~/.jupyter/jupyter_lab_config.py進去一通改&#…

網絡編程(8.15)io模型,IO多路復用(select,poll)

1.使用select函數實現IO多路復用 使用select函數實現IO多路復用的服務器&#xff1a; #include<stdio.h> #include<head.h> #include<netinet/in.h> #include<sys/select.h> #include<arpa/inet.h> #define PROT 1112 #define IP "192.16…

29 | 廣州美食店鋪數據分析

廣州美食店鋪數據分析 一、數據分析項目MVP加/價值主張宣言 隨著經濟的快速發展以及新媒體的興起,美食攻略、美食探店等一系列東西進入大眾的眼球,而人們也會在各大平臺中查找美食推薦,因此本項目做的美食店鋪數據分析也是帶有可行性的。首先通過對廣東省的各市美食店鋪數量…