C++說愛你不容易-7
C++軟件與嵌入式軟件面經(jīng)解析大全(蔣豆芽的秋招打怪之旅)
本章講解點
- 1.1 C++與C的區(qū)別——看看你的理解是否深刻
- 1.2 從代碼到可執(zhí)行文件的過程
- 1.3 extern "C"
- 1.4 宏——到底是什么
- 1.5 內(nèi)聯(lián)函數(shù)
- 1.6 條件編譯
- 1.7 字節(jié)對齊詳解
- 1.8 Const——今天必須把它搞懂
- 1.9 Static作用
- 1.10 volatile和mutable
- 1.11 volatile在嵌入式里的應用
- 1.12 原子操作
- 1.13 指針與引用的區(qū)別
- 1.14 右值引用
- 1.15 面向?qū)ο蟮木幊趟枷?
- 1.16 類
- 1.17 類的成員
- 1.18 友元函數(shù)
- 1.19 初始化列表
- 1.20 this指針
- 1.21 繼承
- 1.22 多態(tài)
- 1.23 虛函數(shù)與重寫
- 1.24 虛構(gòu)造函數(shù)與虛析構(gòu)函數(shù)
- 1.25 函數(shù)重載
- 1.26 操作符重載
- 1.27 迭代器與指針
- 1.28 模板
- 1.29 C++智能指針
- 1.30 四種cast轉(zhuǎn)換
- 1.31 Lambda
- 1.32 function和bind
受眾:本教程適合于C/C++已經(jīng)入門的學生或人士,有一定的編程基礎。
本教程適合于互聯(lián)網(wǎng)、嵌入式軟件求職的學生或人士。
故事背景
蔣 豆 芽:小名豆芽,芳齡十八,蜀中人氏。卑微小碩一枚,科研領域茍延殘喘,研究的是如何炒好一盤豆芽。與大多數(shù)人一樣,學習道路永無止境,間歇性躊躇滿志,持續(xù)性混吃等死。會點編程,對了,是面對對象的那種。不知不覺研二到找工作的時候了,同時還在忙論文,豆芽都禿了,不過豆芽也沒頭發(fā)啊。
隔壁老李:大名老李,蔣豆芽的好朋友,技術(shù)高手,代碼女神。給了蔣豆芽不少的人生指導意見。
導 師:蔣豆芽的老板,研究的課題是每天對豆芽噓寒問暖。
故事引入
蔣 豆 芽:老李,快點快點,我迫不及待想知道最后一個智能指針有什么用。
隔壁老李:豆芽,別急,你干嘛這么急?
蔣 豆 芽:我要去看我小侄女,我小侄女好可愛的,才一歲多,小豆芽成豆芽叔叔了,哈哈。
隔壁老李:那我們趕緊講吧,講完一起去看看侄女,哈哈!
1.29 智能指針
隔壁老李:豆芽,我們上一章講了共享指針,很方便地實現(xiàn)了多個對象指向同一個資源。但是共享指針也存在內(nèi)存泄露的問題。
我們來看看下面的代碼。
#include <iostream> #include <memory> using namespace std; class B; class A{ public: shared_ptr<B> psb; ~A(){ cout << "A delete\n"; } }; class B{ public: shared_ptr<A> psa; ~B(){ cout << "B delete\n"; } }; int main(){ shared_ptr<B> pb(new B()); shared_ptr<A> pa(new A()); pb->psa = pa; pa->psb = pb; cout << pb.use_count() << endl; cout << pa.use_count() << endl; return 0; }
運行代碼如下:
2 2
可以看到主函數(shù)中,pa,pb之間相互引用,兩個資源的引用計數(shù)為2,當跳出函數(shù)時,智能指針pa、pb析構(gòu)時兩個資源引用計數(shù)會減一,但是兩者引用計數(shù)還是為1,導致資源并沒有釋放。這就是共享指針的循環(huán)引用計數(shù)問題。
蔣 豆 芽:這樣啊,所以weak_ptr指針登場了對吧!
隔壁老李:沒錯。weak_ptr是弱引用,weak_ptr的構(gòu)造和析構(gòu)不會引起引用計數(shù)的增加或減少。我們可以將其中一個改為weak_ptr指針就可以了。比如我們將class B里shared_ptr換成weak_ptr,如下:
class B{ public: weak_ptr<A> psa; ~B(){ cout << "B delete\n"; } };
代碼運行如下:
2 1 A delete B delete
蔣 豆 芽:bingo!這次我懂了。所以四種智能指針auto_ptr (C++11被棄用)、unique_ptr、shared_ptr、weak_ptr,最常用的就是unique_ptr和shared_ptr了,我可得好好掌握,面試很常考。
1.30 類型轉(zhuǎn)換
隔壁老李:是的。好了,我們接下來講類型轉(zhuǎn)換。在講之前我們又要復習下C語言中的類型轉(zhuǎn)換。
蔣 豆 芽:你別說了,一個眼神我就懂,我馬上給你回顧一下,老工具人了我。在一個運算表達式中,往往存在自動類型轉(zhuǎn)換的情況。例如:設變量a
的類型是char
,變量b
的類型是int
,變量d
的類型是double
,求解表達式a+b-d
。運算次序是:先計算a+b
,將a
轉(zhuǎn)換為int
型后求和,結(jié)果是int
型;再將a+b
的和轉(zhuǎn)換為double
型,再與d
相減,結(jié)果是double
型。
(1)自動類型轉(zhuǎn)換記住一個圖就可以了。
(2)強制轉(zhuǎn)換
在下面代碼中,
int sum = 7; double mean = sum / 5;
結(jié)果卻是1.0,因為sum
是int
型,sum / 5
,小數(shù)點后面的數(shù)字會丟失,結(jié)果是1,再轉(zhuǎn)為double
,最后是1.0。出現(xiàn)了精度丟失的問題。
強制類型轉(zhuǎn)換是把變量從一種類型轉(zhuǎn)換為另一種數(shù)據(jù)類型。這時對int
類型的sum
強制轉(zhuǎn)換為double
類型。最后結(jié)果就是1.4了。
int sum = 17; double mean = (double) sum/5;
隔壁老李:(笑容邪魅)好的,謝謝我們的工具人豆芽君。C++中,存在很多的類型轉(zhuǎn)換,類間的上下轉(zhuǎn)換,const與非const轉(zhuǎn)換,空與非空轉(zhuǎn)換。
因此C++為了將強制類型轉(zhuǎn)換變得更加明確、控制強制轉(zhuǎn)換的過程,主要將強制轉(zhuǎn)換細化為四種cast轉(zhuǎn)換方式:const_cast、static_cast、dynamic_cast、reinterpret_cast。我們一一講解。
隔壁老李:四種cast轉(zhuǎn)換格式均為
xxxx_cast<類型說明符> (變量或表達式)
const_cast
const_cast用于強制去掉不能被修改的常數(shù)特性,但需要特別注意的是const_cast不是用于去除變量的常量性,而是去除指向常數(shù)對象的指針或引用的常量性,其去除常量性的對象必須為指針或引用。
常量指針被轉(zhuǎn)化成非常量指針,并且仍然指向原來的對象;常量引用被轉(zhuǎn)換成非常量引用,并且仍然指向原來的對象。這句話什么意思呢?我們舉個例子說明。
#include <stdio.h> #include <stdlib.h> #include <string> #include <iostream> using namespace std; int main() { const double a = 7; const double* p = &a; double* q = const_cast<double*>(p); *q = 20; //通過q寫值是未定義的行為 cout << "a=" << a << endl; cout << "*p=" << *p << endl; cout << "*q=" << *q << endl; system("Pause"); return 0; }
運行結(jié)果如下:
a=7 *p=20 *q=20
可以很清楚的看到,const變量
*
p被轉(zhuǎn)換為非const變量*
q,改變*
q的值,const變量的值均發(fā)生了改變。常量指針被轉(zhuǎn)化成非常量指針,并且仍然指向原來的對象,就是這個意思。這樣的操作語法沒有問題,但是邏輯上卻是有問題的,之前在C語言中我們講過,明明是const常量,值卻在中途發(fā)生了改變。所以我們要避免這樣的操作,const_cast盡量少用。
static_cast
static_cast用于將一種數(shù)據(jù)類型強制轉(zhuǎn)換為另一種數(shù)據(jù)類型。什么都可以轉(zhuǎn),最常用。如下:
int a = 7; int b = 3; double result = static_cast<double>(a) / static_cast<double>(b);
但是在進行下行轉(zhuǎn)換(把基類的指針或引用轉(zhuǎn)換為派生類表示)時,由于沒有動態(tài)類型檢查,是不安全的。
向上轉(zhuǎn)換:指子類向基類轉(zhuǎn)換。
向下轉(zhuǎn)換:指基類向子類轉(zhuǎn)換。
這兩種轉(zhuǎn)換,因為子類包含父類,子類轉(zhuǎn)父類是可以任意轉(zhuǎn)的。但是當父類轉(zhuǎn)換成子類時可能出現(xiàn)非法內(nèi)存訪問的問題。
dynamic_cast
正因為static_cast從基類向子類轉(zhuǎn)換時不安全,所以又引入了dynamic_cast。dynamic_cast只能用于含有虛函數(shù)的類轉(zhuǎn)換,用于類向上和向下轉(zhuǎn)換。
dynamic_cast通過判斷變量運行時類型和要轉(zhuǎn)換的類型是否相同來判斷是否能夠進行向下轉(zhuǎn)換。dynamic_cast可以做類之間上下轉(zhuǎn)換,轉(zhuǎn)換的時候會進行類型檢查,類型相等成功轉(zhuǎn)換,類型不等轉(zhuǎn)換失敗。
運用RTTI技術(shù),RTTI是“Runtime Type Information”的縮寫,意思是運行時類型信息,它提供了運行時確定對象類型的方法。在c++層面主要體現(xiàn)在dynamic_cast和typeid,vs中虛函數(shù)表的-1位置存放了指向type_info的指針,對于存在虛函數(shù)的類型,dynamic_cast和typeid都會去查詢type_info
#include <stdio.h> #include <stdlib.h> #include <string> #include <iostream> using namespace std; class Base{ public: Base() {}; virt
剩余60%內(nèi)容,訂閱專欄后可繼續(xù)查看/也可單篇購買
<p> - 本??m合于C/C++已經(jīng)入門的學生或人士,有一定的編程基礎。 - 本專刊適合于互聯(lián)網(wǎng)C++軟件開發(fā)、嵌入式軟件求職的學生或人士。 - 本??依薈語言、C++、操作系統(tǒng)、計算機網(wǎng)絡、嵌入式、算法與數(shù)據(jù)結(jié)構(gòu)等一系列知識點的講解,并且最后總結(jié)出了高頻面試考點(附有答案)共近400道,知識點講解全面。不僅如此,教程還講解了簡歷制作、筆試面試準備、面試技巧等內(nèi)容。 </p> <p> <br /> </p>