● 說(shuō)一下static關(guān)鍵字的作用
參考回答:
1. 全局靜態(tài)變量
在全局變量前加上關(guān)鍵字static,全局變量就定義成一個(gè)全局靜態(tài)變量.
靜態(tài)存儲(chǔ)區(qū),在整個(gè)程序運(yùn)行期間一直存在。
初始化:未經(jīng)初始化的全局靜態(tài)變量會(huì)被自動(dòng)初始化為0(自動(dòng)對(duì)象的值是任意的,除非他被顯式初始化);
作用域:全局靜態(tài)變量在聲明他的文件之外是不可見(jiàn)的,準(zhǔn)確地說(shuō)是從定義之處開(kāi)始,到文件結(jié)尾。
2. 局部靜態(tài)變量
在局部變量之前加上關(guān)鍵字static,局部變量就成為一個(gè)局部靜態(tài)變量。
內(nèi)存中的位置:靜態(tài)存儲(chǔ)區(qū)
初始化:未經(jīng)初始化的全局靜態(tài)變量會(huì)被自動(dòng)初始化為0(自動(dòng)對(duì)象的值是任意的,除非他被顯式初始化);
作用域:作用域仍為局部作用域,當(dāng)定義它的函數(shù)或者語(yǔ)句塊結(jié)束的時(shí)候,作用域結(jié)束。但是當(dāng)局部靜態(tài)變量離開(kāi)作用域后,并沒(méi)有銷(xiāo)毀,而是仍然駐留在內(nèi)存當(dāng)中,只不過(guò)我們不能再對(duì)它進(jìn)行訪問(wèn),直到該函數(shù)再次被調(diào)用,并且值不變;
3. 靜態(tài)函數(shù)
在函數(shù)返回類型前加static,函數(shù)就定義為靜態(tài)函數(shù)。函數(shù)的定義和聲明在默認(rèn)情況下都是extern的,但靜態(tài)函數(shù)只是在聲明他的文件當(dāng)中可見(jiàn),不能被其他文件所用。
函數(shù)的實(shí)現(xiàn)使用static修飾,那么這個(gè)函數(shù)只可在本cpp內(nèi)使用,不會(huì)同其他cpp中的同名函數(shù)引起沖突;
warning:不要再頭文件中聲明static的全局函數(shù),不要在cpp內(nèi)聲明非static的全局函數(shù),如果你要在多個(gè)cpp中復(fù)用該函數(shù),就把它的聲明提到頭文件里去,否則cpp內(nèi)部聲明需加上static修飾;
4. 類的靜態(tài)成員
在類中,靜態(tài)成員可以實(shí)現(xiàn)多個(gè)對(duì)象之間的數(shù)據(jù)共享,并且使用靜態(tài)數(shù)據(jù)成員還不會(huì)破壞隱藏的原則,即保證了安全性。因此,靜態(tài)成員是類的所有對(duì)象中共享的成員,而不是某個(gè)對(duì)象的成員。對(duì)多個(gè)對(duì)象來(lái)說(shuō),靜態(tài)數(shù)據(jù)成員只存儲(chǔ)一處,供所有對(duì)象共用
5. 類的靜態(tài)函數(shù)
靜態(tài)成員函數(shù)和靜態(tài)數(shù)據(jù)成員一樣,它們都屬于類的靜態(tài)成員,它們都不是對(duì)象成員。因此,對(duì)靜態(tài)成員的引用不需要用對(duì)象名。
在靜態(tài)成員函數(shù)的實(shí)現(xiàn)中不能直接引用類中說(shuō)明的非靜態(tài)成員,可以引用類中說(shuō)明的靜態(tài)成員(這點(diǎn)非常重要)。如果靜態(tài)成員函數(shù)中要引用非靜態(tài)成員時(shí),可通過(guò)對(duì)象來(lái)引用。從中可看出,調(diào)用靜態(tài)成員函數(shù)使用如下格式:<類名>::<靜態(tài)成員函數(shù)名>(<參數(shù)表>);
● 說(shuō)一下C++和C的區(qū)別
參考回答:
設(shè)計(jì)思想上:
C++是面向?qū)ο蟮恼Z(yǔ)言,而C是面向過(guò)程的結(jié)構(gòu)化編程語(yǔ)言
語(yǔ)法上:
C++具有重載、繼承和多態(tài)三種特性
C++相比C,增加多許多類型安全的功能,比如強(qiáng)制類型轉(zhuǎn)換、
C++支持范式編程,比如模板類、函數(shù)模板等
● 說(shuō)一下C++中static關(guān)鍵字的作用
參考回答:
對(duì)于函數(shù)定義和代碼塊之外的變量聲明,static修改標(biāo)識(shí)符的鏈接屬性,由默認(rèn)的external變?yōu)閕nternal,作用域和存儲(chǔ)類型不改變,這些符號(hào)只能在聲明它們的源文件中訪問(wèn)。
對(duì)于代碼塊內(nèi)部的變量聲明,static修改標(biāo)識(shí)符的存儲(chǔ)類型,由自動(dòng)變量改為靜態(tài)變量,作用域和鏈接屬性不變。這種變量在程序執(zhí)行之前就創(chuàng)建,在程序執(zhí)行的整個(gè)周期都存在。
對(duì)于被static修飾的普通函數(shù),其只能在定義它的源文件中使用,不能在其他源文件中被引用
對(duì)于被static修飾的類成員變量和成員函數(shù),它們是屬于類的,而不是某個(gè)對(duì)象,所有對(duì)象共享一個(gè)靜態(tài)成員。靜態(tài)成員通過(guò)<類名>::<靜態(tài)成員>來(lái)使用。
● 請(qǐng)說(shuō)一下static的作用
參考回答:
1. 全局靜態(tài)變量
在全局變量前加上關(guān)鍵字static,全局變量就定義成一個(gè)全局靜態(tài)變量。
靜態(tài)存儲(chǔ)區(qū),在整個(gè)程序運(yùn)行期間一直存在。
初始化:未經(jīng)初始化的全局靜態(tài)變量會(huì)被自動(dòng)初始化為0(自動(dòng)對(duì)象的值是任意的,除非他被顯式初始化)。
作用域:全局靜態(tài)變量在聲明他的文件之外是不可見(jiàn)的,準(zhǔn)確地說(shuō)是從定義之處開(kāi)始,到文件結(jié)尾。
2. 局部靜態(tài)變量
在局部變量之前加上關(guān)鍵字static,局部變量就成為一個(gè)局部靜態(tài)變量。
內(nèi)存中的位置:靜態(tài)存儲(chǔ)區(qū)。
初始化:未經(jīng)初始化的全局靜態(tài)變量會(huì)被自動(dòng)初始化為0(自動(dòng)對(duì)象的值是任意的,除非他被顯式初始化)。
作用域:作用域仍為局部作用域,當(dāng)定義它的函數(shù)或者語(yǔ)句塊結(jié)束的時(shí)候,作用域結(jié)束。但是當(dāng)局部靜態(tài)變量離開(kāi)作用域后,并沒(méi)有銷(xiāo)毀,而是仍然駐留在內(nèi)存當(dāng)中,只不過(guò)我們不能再對(duì)它進(jìn)行訪問(wèn),直到該函數(shù)再次被調(diào)用,并且值不變。
3. 靜態(tài)函數(shù)
在函數(shù)返回類型前加static,函數(shù)就定義為靜態(tài)函數(shù)。函數(shù)的定義和聲明在默認(rèn)情況下都是extern的,但靜態(tài)函數(shù)只是在聲明他的文件當(dāng)中可見(jiàn),不能被其他文件所用。
函數(shù)的實(shí)現(xiàn)使用static修飾,那么這個(gè)函數(shù)只可在本cpp內(nèi)使用,不會(huì)同其他cpp中的同名函數(shù)引起沖突。
warning:不要再頭文件中聲明static的全局函數(shù),不要在cpp內(nèi)聲明非static的全局函數(shù),如果你要在多個(gè)cpp中復(fù)用該函數(shù),就把它的聲明提到頭文件里去,否則cpp內(nèi)部聲明需加上static修飾。
4. 類的靜態(tài)成員
在類中,靜態(tài)成員可以實(shí)現(xiàn)多個(gè)對(duì)象之間的數(shù)據(jù)共享,并且使用靜態(tài)數(shù)據(jù)成員還不會(huì)破壞隱藏的原則,即保證了安全性。因此,靜態(tài)成員是類的所有對(duì)象中共享的成員,而不是某個(gè)對(duì)象的成員。對(duì)多個(gè)對(duì)象來(lái)說(shuō),靜態(tài)數(shù)據(jù)成員只存儲(chǔ)一處,供所有對(duì)象共用。
5. 類的靜態(tài)函數(shù)
靜態(tài)成員函數(shù)和靜態(tài)數(shù)據(jù)成員一樣,它們都屬于類的靜態(tài)成員,它們都不是對(duì)象成員。因此,對(duì)靜態(tài)成員的引用不需要用對(duì)象名。
在靜態(tài)成員函數(shù)的實(shí)現(xiàn)中不能直接引用類中說(shuō)明的非靜態(tài)成員,可以引用類中說(shuō)明的靜態(tài)成員(這點(diǎn)非常重要)。如果靜態(tài)成員函數(shù)中要引用非靜態(tài)成員時(shí),可通過(guò)對(duì)象來(lái)引用。從中可看出,調(diào)用靜態(tài)成員函數(shù)使用如下格式:<類名>::<靜態(tài)成員函數(shù)名>(<參數(shù)表>);

為大家準(zhǔn)備了很多面試資料和學(xué)習(xí)入門(mén)+進(jìn)階+深入的資料,關(guān)注公zhon號(hào),名企內(nèi)推軍,回復(fù) 資料 二字可獲取
● 說(shuō)一說(shuō)c++中四種cast轉(zhuǎn)換
參考回答:
C++中四種類型轉(zhuǎn)換是:static_cast, dynamic_cast, const_cast, reinterpret_cast
1、const_cast
用于將const變量轉(zhuǎn)為非const
2、static_cast
用于各種隱式轉(zhuǎn)換,比如非const轉(zhuǎn)const,void*轉(zhuǎn)指針等, static_cast能用于多態(tài)向上轉(zhuǎn)化,如果向下轉(zhuǎn)能成功但是不安全,結(jié)果未知;
3、dynamic_cast
用于動(dòng)態(tài)類型轉(zhuǎn)換。只能用于含有虛函數(shù)的類,用于類層次間的向上和向下轉(zhuǎn)化。只能轉(zhuǎn)指針或引用。向下轉(zhuǎn)化時(shí),如果是非法的對(duì)于指針?lè)祷豊ULL,對(duì)于引用拋異常。要深入了解內(nèi)部轉(zhuǎn)換的原理。
向上轉(zhuǎn)換:指的是子類向基類的轉(zhuǎn)換
向下轉(zhuǎn)換:指的是基類向子類的轉(zhuǎn)換
它通過(guò)判斷在執(zhí)行到該語(yǔ)句的時(shí)候變量的運(yùn)行時(shí)類型和要轉(zhuǎn)換的類型是否相同來(lái)判斷是否能夠進(jìn)行向下轉(zhuǎn)換。
4、reinterpret_cast
幾乎什么都可以轉(zhuǎn),比如將int轉(zhuǎn)指針,可能會(huì)出問(wèn)題,盡量少用;
5、為什么不使用C的強(qiáng)制轉(zhuǎn)換?
C的強(qiáng)制轉(zhuǎn)換表面上看起來(lái)功能強(qiáng)大什么都能轉(zhuǎn),但是轉(zhuǎn)化不夠明確,不能進(jìn)行錯(cuò)誤檢查,容易出錯(cuò)。
● 請(qǐng)說(shuō)一下C/C++ 中指針和引用的區(qū)別?
參考回答:
1.指針有自己的一塊空間,而引用只是一個(gè)別名;
2.使用sizeof看一個(gè)指針的大小是4,而引用則是被引用對(duì)象的大??;
3.指針可以被初始化為NULL,而引用必須被初始化且必須是一個(gè)已有對(duì)象 的引用;
4.作為參數(shù)傳遞時(shí),指針需要被解引用才可以對(duì)對(duì)象進(jìn)行操作,而直接對(duì)引 用的修改都會(huì)改變引用所指向的對(duì)象;
5.可以有const指針,但是沒(méi)有const引用;
6.指針在使用中可以指向其它對(duì)象,但是引用只能是一個(gè)對(duì)象的引用,不能 被改變;
7.指針可以有多級(jí)指針(**p),而引用至于一級(jí);
8.指針和引用使用++運(yùn)算符的意義不一樣;
9.如果返回動(dòng)態(tài)內(nèi)存分配的對(duì)象或者內(nèi)存,必須使用指針,引用可能引起內(nèi)存泄露。
● 給定三角形ABC和一點(diǎn)P(x,y,z),判斷點(diǎn)P是否在ABC內(nèi),給出思路并手寫(xiě)代碼
參考回答:
根據(jù)面積法,如果P在三角形ABC內(nèi),那么三角形ABP的面積+三角形BCP的面積+三角形ACP的面積應(yīng)該等于三角形ABC的面積。算法如下:
<pre style="margin: 12px 0px; padding: 0.25em 1em; font-weight: 400; font-size: 14px; position: relative; border-left: 2px solid rgb(26, 188, 156); background: rgb(246, 248, 250); word-break: break-word; font-family: Courier, "Courier New", monospace; white-space: pre-wrap; overflow-wrap: normal; overflow: auto; line-height: 1.45; border-radius: 0px 3px 3px 0px; border-top: none; border-right: none; border-bottom: none; border-image: initial; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">#include <iostream>
include <math.h>
using namespace std;
define ABS_FLOAT_0 0.0001
struct point_float
{
float x;
float y;
};</pre>
/**
- @brief 計(jì)算三角形面積
*/
<pre style="margin: 12px 0px; padding: 0.25em 1em; font-weight: 400; font-size: 14px; position: relative; border-left: 2px solid rgb(26, 188, 156); background: rgb(246, 248, 250); word-break: break-word; font-family: Courier, "Courier New", monospace; white-space: pre-wrap; overflow-wrap: normal; overflow: auto; line-height: 1.45; border-radius: 0px 3px 3px 0px; border-top: none; border-right: none; border-bottom: none; border-image: initial; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">float GetTriangleSquar(const point_float pt0, const point_float pt1, const point_float pt2)
{
point_float AB, BC;
AB.x = pt1.x - pt0.x;
AB.y = pt1.y - pt0.y;
BC.x = pt2.x - pt1.x;
BC.y = pt2.y - pt1.y;
return fabs((AB.x * BC.y - AB.y * BC.x)) / 2.0f;
}</pre>
/**
- @brief 判斷給定一點(diǎn)是否在三角形內(nèi)或邊上
*/
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
bool IsInTriangle(``const point_float A, ``const point_float B, ``const point_float C, ``const point_float D)
{
float SABC, SADB, SBDC, SADC;
SABC = GetTriangleSquar(A, B, C);
SADB = GetTriangleSquar(A, D, B);
SBDC = GetTriangleSquar(B, D, C);
SADC = GetTriangleSquar(A, D, C);
float SumSuqar = SADB + SBDC + SADC;
if ((-ABS_FLOAT_0 < (SABC - SumSuqar)) && ((SABC - SumSuqar) < ABS_FLOAT_0))
{
return true``;
}
else
{
return false``;
}
}
|
● 請(qǐng)你說(shuō)一下你理解的c++中的smart pointer四個(gè)智能指針: shared_ptr,unique_ptr,weak_ptr,auto_ptr
參考回答:
C++里面的四個(gè)智能指針: auto_ptr, shared_ptr, weak_ptr, unique_ptr 其中后三個(gè)是c++11支持,并且第一個(gè)已經(jīng)被11棄用。
為什么要使用智能指針:
智能指針的作用是管理一個(gè)指針,因?yàn)榇嬖谝韵逻@種情況:申請(qǐng)的空間在函數(shù)結(jié)束時(shí)忘記釋放,造成內(nèi)存泄漏。使用智能指針可以很大程度上的避免這個(gè)問(wèn)題,因?yàn)橹悄苤羔樉褪且粋€(gè)類,當(dāng)超出了類的作用域是,類會(huì)自動(dòng)調(diào)用析構(gòu)函數(shù),析構(gòu)函數(shù)會(huì)自動(dòng)釋放資源。所以智能指針的作用原理就是在函數(shù)結(jié)束時(shí)自動(dòng)釋放內(nèi)存空間,不需要手動(dòng)釋放內(nèi)存空間。
1. auto_ptr(c++98的方案,cpp11已經(jīng)拋棄)
采用所有權(quán)模式。
<pre style="margin: 12px 0px; padding: 0.25em 1em; font-weight: 400; font-size: 14px; position: relative; border-left: 2px solid rgb(26, 188, 156); background: rgb(246, 248, 250); word-break: break-word; font-family: Courier, "Courier New", monospace; white-space: pre-wrap; overflow-wrap: normal; overflow: auto; line-height: 1.45; border-radius: 0px 3px 3px 0px; border-top: none; border-right: none; border-bottom: none; border-image: initial; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">auto_ptr< string> p1 (new string ("I reigned lonely as a cloud.”));
auto_ptr<string> p2;
p2 = p1; //auto_ptr不會(huì)報(bào)錯(cuò).</pre>
此時(shí)不會(huì)報(bào)錯(cuò),p2剝奪了p1的所有權(quán),但是當(dāng)程序運(yùn)行時(shí)訪問(wèn)p1將會(huì)報(bào)錯(cuò)。所以auto_ptr的缺點(diǎn)是:存在潛在的內(nèi)存崩潰問(wèn)題!
2. unique_ptr(替換auto_ptr)
unique_ptr實(shí)現(xiàn)獨(dú)占式擁有或嚴(yán)格擁有概念,保證同一時(shí)間內(nèi)只有一個(gè)智能指針可以指向該對(duì)象。它對(duì)于避免資源泄露(例如“以new創(chuàng)建對(duì)象后因?yàn)榘l(fā)生異常而忘記調(diào)用delete”)特別有用。
采用所有權(quán)模式,還是上面那個(gè)例子
|
1
2
3
|
unique_ptr<string> p3 (``new string (``"auto"``)); ``//#4
unique_ptr<string> p4; ``//#5
p4 = p3;``//此時(shí)會(huì)報(bào)錯(cuò)??!
|
編譯器認(rèn)為p4=p3非法,避免了p3不再指向有效數(shù)據(jù)的問(wèn)題。因此,unique_ptr比auto_ptr更安全。
另外unique_ptr還有更聰明的地方:當(dāng)程序試圖將一個(gè) unique_ptr 賦值給另一個(gè)時(shí),如果源 unique_ptr 是個(gè)臨時(shí)右值,編譯器允許這么做;如果源 unique_ptr 將存在一段時(shí)間,編譯器將禁止這么做,比如:
<pre style="margin: 12px 0px; padding: 0.25em 1em; font-weight: 400; font-size: 14px; position: relative; border-left: 2px solid rgb(26, 188, 156); background: rgb(246, 248, 250); word-break: break-word; font-family: Courier, "Courier New", monospace; white-space: pre-wrap; overflow-wrap: normal; overflow: auto; line-height: 1.45; border-radius: 0px 3px 3px 0px; border-top: none; border-right: none; border-bottom: none; border-image: initial; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">unique_ptr<string> pu1(new string ("hello world"));
unique_ptr<string> pu2;
pu2 = pu1; // #1 not allowed
unique_ptr<string> pu3;
pu3 = unique_ptr<string>(new string ("You")); // #2 allowed</pre>
其中#1留下懸掛的unique_ptr(pu1),這可能導(dǎo)致危害。而#2不會(huì)留下懸掛的unique_ptr,因?yàn)樗{(diào)用 unique_ptr 的構(gòu)造函數(shù),該構(gòu)造函數(shù)創(chuàng)建的臨時(shí)對(duì)象在其所有權(quán)讓給 pu3 后就會(huì)被銷(xiāo)毀。這種隨情況而已的行為表明,unique_ptr 優(yōu)于允許兩種賦值的auto_ptr 。
注:如果確實(shí)想執(zhí)行類似與#1的操作,要安全的重用這種指針,可給它賦新值。C++有一個(gè)標(biāo)準(zhǔn)庫(kù)函數(shù)std::move(),讓你能夠?qū)⒁粋€(gè)unique_ptr賦給另一個(gè)。例如:
<pre style="margin: 12px 0px; padding: 0.25em 1em; font-weight: 400; font-size: 14px; position: relative; border-left: 2px solid rgb(26, 188, 156); background: rgb(246, 248, 250); word-break: break-word; font-family: Courier, "Courier New", monospace; white-space: pre-wrap; overflow-wrap: normal; overflow: auto; line-height: 1.45; border-radius: 0px 3px 3px 0px; border-top: none; border-right: none; border-bottom: none; border-image: initial; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">unique_ptr<string> ps1, ps2;
ps1 = demo("hello");
ps2 = move(ps1);
ps1 = demo("alexia");
cout << *ps2 << *ps1 << endl;</pre>
3. shared_ptr
shared_ptr實(shí)現(xiàn)共享式擁有概念。多個(gè)智能指針可以指向相同對(duì)象,該對(duì)象和其相關(guān)資源會(huì)在“最后一個(gè)引用被銷(xiāo)毀”時(shí)候釋放。從名字share就可以看出了資源可以被多個(gè)指針共享,它使用計(jì)數(shù)機(jī)制來(lái)表明資源被幾個(gè)指針共享??梢酝ㄟ^(guò)成員函數(shù)use_count()來(lái)查看資源的所有者個(gè)數(shù)。除了可以通過(guò)new來(lái)構(gòu)造,還可以通過(guò)傳入auto_ptr, unique_ptr,weak_ptr來(lái)構(gòu)造。當(dāng)我們調(diào)用release()時(shí),當(dāng)前指針會(huì)釋放資源所有權(quán),計(jì)數(shù)減一。當(dāng)計(jì)數(shù)等于0時(shí),資源會(huì)被釋放。
shared_ptr 是為了解決 auto_ptr 在對(duì)象所有權(quán)上的局限性(auto_ptr 是獨(dú)占的), 在使用引用計(jì)數(shù)的機(jī)制上提供了可以共享所有權(quán)的智能指針。
成員函數(shù):
use_count 返回引用計(jì)數(shù)的個(gè)數(shù)
unique 返回是否是獨(dú)占所有權(quán)( use_count 為 1)
swap 交換兩個(gè) shared_ptr 對(duì)象(即交換所擁有的對(duì)象)
reset 放棄內(nèi)部對(duì)象的所有權(quán)或擁有對(duì)象的變更, 會(huì)引起原有對(duì)象的引用計(jì)數(shù)的減少
get 返回內(nèi)部對(duì)象(指針), 由于已經(jīng)重載了()方法, 因此和直接使用對(duì)象是一樣的.如 shared_ptr<int> sp(new int(1)); sp 與 sp.get()是等價(jià)的
4. weak_ptr
weak_ptr 是一種不控制對(duì)象生命周期的智能指針, 它指向一個(gè) shared_ptr 管理的對(duì)象. 進(jìn)行該對(duì)象的內(nèi)存管理的是那個(gè)強(qiáng)引用的 shared_ptr. weak_ptr只是提供了對(duì)管理對(duì)象的一個(gè)訪問(wèn)手段。weak_ptr 設(shè)計(jì)的目的是為配合 shared_ptr 而引入的一種智能指針來(lái)協(xié)助 shared_ptr 工作, 它只可以從一個(gè) shared_ptr 或另一個(gè) weak_ptr 對(duì)象構(gòu)造, 它的構(gòu)造和析構(gòu)不會(huì)引起引用記數(shù)的增加或減少。weak_ptr是用來(lái)解決shared_ptr相互引用時(shí)的死鎖問(wèn)題,如果說(shuō)兩個(gè)shared_ptr相互引用,那么這兩個(gè)指針的引用計(jì)數(shù)永遠(yuǎn)不可能下降為0,資源永遠(yuǎn)不會(huì)釋放。它是對(duì)對(duì)象的一種弱引用,不會(huì)增加對(duì)象的引用計(jì)數(shù),和shared_ptr之間可以相互轉(zhuǎn)化,shared_ptr可以直接賦值給它,它可以通過(guò)調(diào)用lock函數(shù)來(lái)獲得shared_ptr。
<pre style="margin: 12px 0px; padding: 0.25em 1em; font-weight: 400; font-size: 14px; position: relative; border-left: 2px solid rgb(26, 188, 156); background: rgb(246, 248, 250); word-break: break-word; font-family: Courier, "Courier New", monospace; white-space: pre-wrap; overflow-wrap: normal; overflow: auto; line-height: 1.45; border-radius: 0px 3px 3px 0px; border-top: none; border-right: none; border-bottom: none; border-image: initial; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">class B;
class A
{
public:
shared_ptr<B> pb_;
~A()
{
cout<<"A delete\n";
}
};
class B
{
public:
shared_ptr<A> pa_;
~B()
{
cout<<"B delete\n";
}
};
void fun()
{
shared_ptr<B> pb(new B());
shared_ptr<A> pa(new A());
pb->pa_ = pa;
pa->pb_ = pb;
cout<<pb.use_count()<<endl;
cout<<pa.use_count()<<endl;
}
int main()
{
fun();
return 0;
}</pre>
可以看到fun函數(shù)中pa ,pb之間互相引用,兩個(gè)資源的引用計(jì)數(shù)為2,當(dāng)要跳出函數(shù)時(shí),智能指針pa,pb析構(gòu)時(shí)兩個(gè)資源引用計(jì)數(shù)會(huì)減一,但是兩者引用計(jì)數(shù)還是為1,導(dǎo)致跳出函數(shù)時(shí)資源沒(méi)有被釋放(A B的析構(gòu)函數(shù)沒(méi)有被調(diào)用),如果把其中一個(gè)改為weak_ptr就可以了,我們把類A里面的shared_ptr pb_; 改為weak_ptr pb_; 運(yùn)行結(jié)果如下,這樣的話,資源B的引用開(kāi)始就只有1,當(dāng)pb析構(gòu)時(shí),B的計(jì)數(shù)變?yōu)?,B得到釋放,B釋放的同時(shí)也會(huì)使A的計(jì)數(shù)減一,同時(shí)pa析構(gòu)時(shí)使A的計(jì)數(shù)減一,那么A的計(jì)數(shù)為0,A得到釋放。
注意的是我們不能通過(guò)weak_ptr直接訪問(wèn)對(duì)象的方法,比如B對(duì)象中有一個(gè)方法print(),我們不能這樣訪問(wèn),pa->pb_->print(); 英文pb_是一個(gè)weak_ptr,應(yīng)該先把它轉(zhuǎn)化為shared_ptr,如:shared_ptr p = pa->pb_.lock(); p->print();
● 怎么判斷一個(gè)數(shù)是二的倍數(shù),怎么求一個(gè)數(shù)中有幾個(gè)1,說(shuō)一下你的思路并手寫(xiě)代碼
參考回答:
1、判斷一個(gè)數(shù)是不是二的倍數(shù),即判斷該數(shù)二進(jìn)制末位是不是0:
a % 2 == 0 或者a & 0x0001 == 0。
2、求一個(gè)數(shù)中1的位數(shù),可以直接逐位除十取余判斷:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
int fun(long x)
{
int _count = ``0``;
while(x)
{
if(x % ``10 == ``1``)
++_count;
x /= ``10``;
}
return _count;
}
int main()
{
cout << fun(``123321``) << endl;
return ``0``;
}
|
● 請(qǐng)回答一下數(shù)組和指針的區(qū)別
參考回答:
指針和數(shù)組的主要區(qū)別如下:
|
指針
|
數(shù)組
|
|
保存數(shù)據(jù)的地址
|
保存數(shù)據(jù)
|
|
間接訪問(wèn)數(shù)據(jù),首先獲得指針的內(nèi)容,然后將其作為地址,從該地址中提取數(shù)據(jù)
|
直接訪問(wèn)數(shù)據(jù),
|
|
通常用于動(dòng)態(tài)的數(shù)據(jù)結(jié)構(gòu)
|
通常用于固定數(shù)目且數(shù)據(jù)類型相同的元素
|
|
通過(guò)Malloc分配內(nèi)存,free釋放內(nèi)存
|
隱式的分配和刪除
|
|
通常指向匿名數(shù)據(jù),操作匿名函數(shù)
|
自身即為數(shù)據(jù)名
|
● 請(qǐng)你回答一下野指針是什么?
參考回答:
野指針就是指向一個(gè)已刪除的對(duì)象或者未申請(qǐng)?jiān)L問(wèn)受限內(nèi)存區(qū)域的指針
● 請(qǐng)你介紹一下C++中的智能指針
參考回答:
智能指針主要用于管理在堆上分配的內(nèi)存,它將普通的指針?lè)庋b為一個(gè)棧對(duì)象。當(dāng)棧對(duì)象的生存周期結(jié)束后,會(huì)在析構(gòu)函數(shù)中釋放掉申請(qǐng)的內(nèi)存,從而防止內(nèi)存泄漏。C++ 11中最常用的智能指針類型為shared_ptr,它采用引用計(jì)數(shù)的方法,記錄當(dāng)前內(nèi)存資源被多少個(gè)智能指針引用。該引用計(jì)數(shù)的內(nèi)存在堆上分配。當(dāng)新增一個(gè)時(shí)引用計(jì)數(shù)加1,當(dāng)過(guò)期時(shí)引用計(jì)數(shù)減一。只有引用計(jì)數(shù)為0時(shí),智能指針才會(huì)自動(dòng)釋放引用的內(nèi)存資源。對(duì)shared_ptr進(jìn)行初始化時(shí)不能將一個(gè)普通指針直接賦值給智能指針,因?yàn)橐粋€(gè)是指針,一個(gè)是類。可以通過(guò)make_shared函數(shù)或者通過(guò)構(gòu)造函數(shù)傳入普通指針。并可以通過(guò)get函數(shù)獲得普通指針。
● 請(qǐng)你回答一下智能指針有沒(méi)有內(nèi)存泄露的情況
參考回答:
當(dāng)兩個(gè)對(duì)象相互使用一個(gè)shared_ptr成員變量指向?qū)Ψ?,?huì)造成循環(huán)引用,使引用計(jì)數(shù)失效,從而導(dǎo)致內(nèi)存泄漏。例如:上述代碼中,parent有一個(gè)shared_ptr類型的成員指向孩子,而child也有一個(gè)shared_ptr類型的成員指向父親。然后在創(chuàng)建孩子和父親對(duì)象時(shí)也使用了智能指針c和p,隨后將c和p分別又賦值給child的智能指針成員parent和parent的智能指針成員child。從而形成了一個(gè)循環(huán)引用:
● 請(qǐng)你來(lái)說(shuō)一下智能指針的內(nèi)存泄漏如何解決
參考回答:
為了解決循環(huán)引用導(dǎo)致的內(nèi)存泄漏,引入了weak_ptr弱指針,weak_ptr的構(gòu)造函數(shù)不會(huì)修改引用計(jì)數(shù)的值,從而不會(huì)對(duì)對(duì)象的內(nèi)存進(jìn)行管理,其類似一個(gè)普通指針,但不指向引用計(jì)數(shù)的共享內(nèi)存,但是其可以檢測(cè)到所管理的對(duì)象是否已經(jīng)被釋放,從而避免非法訪問(wèn)。
● 請(qǐng)你理解的c++中的引用和指針
參考回答:
定義:
1、引用:
C++是C語(yǔ)言的繼承,它可進(jìn)行過(guò)程化程序設(shè)計(jì),又可以進(jìn)行以抽象數(shù)據(jù)類型為特點(diǎn)的基于對(duì)象的程序設(shè)計(jì),還可以進(jìn)行以繼承和多態(tài)為特點(diǎn)的面向?qū)ο蟮某绦蛟O(shè)計(jì)。引用就是C++對(duì)C語(yǔ)言的重要擴(kuò)充。引用就是某一變量的一個(gè)別名,對(duì)引用的操作與對(duì)變量直接操作完全一樣。引用的聲明方法:類型標(biāo)識(shí)符 &引用名=目標(biāo)變量名;引用引入了對(duì)象的一個(gè)同義詞。定義引用的表示方法與定義指針相似,只是用&代替了*。
2、指針:
指針利用地址,它的值直接指向存在電腦存儲(chǔ)器中另一個(gè)地方的值。由于通過(guò)地址能找到所需的變量單元,可以說(shuō),地址指向該變量單元。因此,將地址形象化的稱為“指針”。意思是通過(guò)它能找到以它為地址的內(nèi)存單元。
區(qū)別:
1、指針有自己的一塊空間,而引用只是一個(gè)別名;
2、使用sizeof看一個(gè)指針的大小是4,而引用則是被引用對(duì)象的大??;
3、指針可以被初始化為NULL,而引用必須被初始化且必須是一個(gè)已有對(duì)象的引用;
4、作為參數(shù)傳遞時(shí),指針需要被解引用才可以對(duì)對(duì)象進(jìn)行操作,而直接對(duì)引用的修改都會(huì)改變引用所指向的對(duì)象;
5、可以有const指針,但是沒(méi)有const引用;
6、指針在使用中可以指向其它對(duì)象,但是引用只能是一個(gè)對(duì)象的引用,不能 被改變;
7、指針可以有多級(jí)指針(**p),而引用至于一級(jí);
8、指針和引用使用++運(yùn)算符的意義不一樣;
9、如果返回動(dòng)態(tài)內(nèi)存分配的對(duì)象或者內(nèi)存,必須使用指針,引用可能引起內(nèi)存泄露。