BAT面試 基礎(chǔ)篇(一)

● 說(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ù)表>);


image.png

為大家準(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)存泄漏。例如:
image
image
image

上述代碼中,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)存泄露。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 過(guò)得每一天都比以前努力。最近看簡(jiǎn)書(shū)的文章覺(jué)得上首頁(yè)的文章,并不是寫(xiě)的很好。自己每天也堅(jiān)持閱讀,準(zhǔn)備過(guò)年的時(shí)候能給自...
    曾曾的麻麻閱讀 193評(píng)論 0 0
  • 一個(gè)男性朋友昨晚在說(shuō)說(shuō)里發(fā)表了這樣一段話,說(shuō)是段還有些太過(guò)牽強(qiáng)了其實(shí)就是一句話。 “可能他窮他丑他矮所...
    吳小姐閱讀 486評(píng)論 0 3
  • 思維導(dǎo)圖如何運(yùn)用于英語(yǔ)學(xué)科呢?這是我們要分享的。 學(xué)科思維導(dǎo)圖與傳統(tǒng)思維導(dǎo)圖是有一定差異的。傳統(tǒng)思維導(dǎo)圖...
    寧歌911閱讀 315評(píng)論 0 0
  • 在2016年8月,《新英格蘭醫(yī)學(xué)雜志》上發(fā)表了一篇引人注目的報(bào)告,報(bào)告內(nèi)容是關(guān)于癌癥和身體脂肪的關(guān)系。 目前,13...
    我微微一笑閱讀 1,263評(píng)論 1 4

友情鏈接更多精彩內(nèi)容