关键字库函数
關(guān)鍵字庫(kù)函數(shù)
轉(zhuǎn)自:https://leetcode-cn.com/leetbook/read/cpp-interview-highlights/ej3mx1/
sizeof和strlen的區(qū)別
strlen 是頭文件<cstring> 中的函數(shù),sizeof 是 C++ 中的運(yùn)算符。
strlen 測(cè)量的是字符串的實(shí)際長(zhǎng)度(其源代碼如下),以 \0 結(jié)束。而 sizeof 測(cè)量的是字符數(shù)組的分配大小。
strlen 源代碼
size_t strlen(const char *str) {size_t length = 0;while (*str++)++length;return length; }舉例:
#include <iostream> #include <cstring>using namespace std;int main() {char arr[10] = "hello";cout << strlen(arr) << endl; // 5cout << sizeof(arr) << endl; // 10return 0; }若字符數(shù)組 arr 作為函數(shù)的形參,sizeof(arr) 中 arr 被當(dāng)作字符指針來(lái)處理,strlen(arr) 中 arr 依然是字符數(shù)組,從下述程序的運(yùn)行結(jié)果中就可以看出。
#include <iostream> #include <cstring>using namespace std;void size_of(char arr[]) {cout << sizeof(arr) << endl; // warning: 'sizeof' on array function parameter 'arr' will return size of 'char*' .cout << strlen(arr) << endl; }int main() {char arr[20] = "hello";size_of(arr); return 0; } /* 輸出結(jié)果: 8 5 */strlen 本身是庫(kù)函數(shù),因此在程序運(yùn)行過(guò)程中,計(jì)算長(zhǎng)度;而 sizeof 在編譯時(shí),計(jì)算長(zhǎng)度;
sizeof 的參數(shù)可以是類(lèi)型,也可以是變量;strlen 的參數(shù)必須是 char* 類(lèi)型的變量。
lambda 表達(dá)式(匿名函數(shù))的具體應(yīng)用和使用場(chǎng)景
lambda 表達(dá)式的定義形式如下:
[capture list] (parameter list) -> reurn type {function body }其中:
- capture list:捕獲列表,指 lambda 表達(dá)式所在函數(shù)中定義的局部變量的列表,通常為空,但如果函數(shù)體中用到了 lambda 表達(dá)式所在函數(shù)的局部變量,必須捕獲該變量,即將此變量寫(xiě)在捕獲列表中。捕獲方式分為:引用捕獲方式 [&]、值捕獲方式 [=]。
- return type、parameter list、function body:分別表示返回值類(lèi)型、參數(shù)列表、函數(shù)體,和普通函數(shù)一樣。
舉例:
lambda 表達(dá)式常搭配排序算法使用。
#include <iostream> #include <vector> #include <algorithm> using namespace std;int main() {vector<int> arr = {3, 4, 76, 12, 54, 90, 34};sort(arr.begin(), arr.end(), [](int a, int b) { return a > b; }); // 降序排序for (auto a : arr){cout << a << " ";}return 0; } /* 運(yùn)行結(jié)果:90 76 54 34 12 4 3 */explicit 的作用(如何避免編譯器進(jìn)行隱式類(lèi)型轉(zhuǎn)換)
作用:用來(lái)聲明類(lèi)構(gòu)造函數(shù)是顯示調(diào)用的,而非隱式調(diào)用,可以阻止調(diào)用構(gòu)造函數(shù)時(shí)進(jìn)行隱式轉(zhuǎn)換。只可用于修飾單參構(gòu)造函數(shù),因?yàn)闊o(wú)參構(gòu)造函數(shù)和多參構(gòu)造函數(shù)本身就是顯示調(diào)用的,再加上 explicit 關(guān)鍵字也沒(méi)有什么意義。
隱式轉(zhuǎn)換:
#include <iostream> #include <cstring> using namespace std;class A { public:int var;A(int tmp){var = tmp;} }; int main() {A ex = 10; // 發(fā)生了隱式轉(zhuǎn)換return 0; }上述代碼中,A ex = 10; 在編譯時(shí),進(jìn)行了隱式轉(zhuǎn)換,將 10 轉(zhuǎn)換成 A 類(lèi)型的對(duì)象,然后將該對(duì)象賦值給 ex,等同于如下操作:
為了避免隱式轉(zhuǎn)換,可用 explicit 關(guān)鍵字進(jìn)行聲明:
#include <iostream> #include <cstring> using namespace std;class A { public:int var;explicit A(int tmp){var = tmp;cout << var << endl;} }; int main() {A ex(100);A ex1 = 10; // error: conversion from 'int' to non-scalar type 'A' requestedreturn 0; }static關(guān)鍵字
C和C++static的區(qū)別
-
在 C 語(yǔ)言中,使用 static 可以定義局部靜態(tài)變量、外部靜態(tài)變量、靜態(tài)函數(shù)
-
在 C++ 中,使用 static 可以定義局部靜態(tài)變量、外部靜態(tài)變量、靜態(tài)函數(shù)、靜態(tài)成員變量和靜態(tài)成員函數(shù)。因?yàn)?C++ 中有類(lèi)的概念,靜態(tài)成員變量、靜態(tài)成員函數(shù)都是與類(lèi)有關(guān)的概念。
static的作用
作用:
static 定義靜態(tài)變量,靜態(tài)函數(shù)。
- 保持變量?jī)?nèi)容持久:static 作用于局部變量,改變了局部變量的生存周期,使得該變量存在于定義后直到程序運(yùn)行結(jié)束的這段時(shí)間。
-
隱藏:static 作用于全局變量和函數(shù),改變了全局變量和函數(shù)的作用域,使得全局變量和函數(shù)只能在定義它的文件中使用,在源文件中不具有全局可見(jiàn)性。(注:普通全局變量和函數(shù)具有全局可見(jiàn)性,即其他的源文件也可以使用。)
-
static 作用于類(lèi)的成員變量和類(lèi)的成員函數(shù),使得類(lèi)變量或者類(lèi)成員函數(shù)和類(lèi)有關(guān),也就是說(shuō)可以不定義類(lèi)的對(duì)象就可以通過(guò)類(lèi)訪(fǎng)問(wèn)這些靜態(tài)成員。注意:類(lèi)的靜態(tài)成員函數(shù)中只能訪(fǎng)問(wèn)靜態(tài)成員變量或者靜態(tài)成員函數(shù),不能將靜態(tài)成員函數(shù)定義成虛函數(shù)。
static在類(lèi)中使用的注意事項(xiàng)(定義、初始化和使用)
static 靜態(tài)成員變量:
靜態(tài)成員變量是在類(lèi)內(nèi)進(jìn)行聲明,在類(lèi)外進(jìn)行定義和初始化,在類(lèi)外進(jìn)行定義和初始化的時(shí)候不要出現(xiàn) static 關(guān)鍵字和private、public、protected 訪(fǎng)問(wèn)規(guī)則。
靜態(tài)成員變量相當(dāng)于類(lèi)域中的全局變量,被類(lèi)的所有對(duì)象所共享,包括派生類(lèi)的對(duì)象。
靜態(tài)成員變量可以作為成員函數(shù)的參數(shù),而普通成員變量不可以。
#include <iostream> using namespace std;class A { public:static int s_var;int var;void fun1(int i = s_var); // 正確,靜態(tài)成員變量可以作為成員函數(shù)的參數(shù)void fun2(int i = var); // error: invalid use of non-static data member 'A::var' }; int main() {return 0; }靜態(tài)數(shù)據(jù)成員的類(lèi)型可以是所屬類(lèi)的類(lèi)型,而普通數(shù)據(jù)成員的類(lèi)型只能是該類(lèi)類(lèi)型的指針或引用。
#include <iostream> using namespace std;class A { public:static A s_var; // 正確,靜態(tài)數(shù)據(jù)成員A var; // error: field 'var' has incomplete type 'A'A *p; // 正確,指針A &var1; // 正確,引用 };int main() {return 0; }static 靜態(tài)成員函數(shù):
static 全局變量和普通全局變量的異同
相同點(diǎn):
- 存儲(chǔ)方式:普通全局變量和 static 全局變量都是靜態(tài)存儲(chǔ)方式。
不同點(diǎn):
- 作用域:普通全局變量的作用域是整個(gè)源程序,當(dāng)一個(gè)源程序由多個(gè)源文件組成時(shí),普通全局變量在各個(gè)源文件中都是有效的;靜態(tài)全局變量則限制了其作用域,即只在定義該變量的源文件內(nèi)有效,在同一源程序的其它源文件中不能使用它。由于靜態(tài)全局變量的作用域限于一個(gè)源文件內(nèi),只能為該源文件內(nèi)的函數(shù)公用,因此可以避免在其他源文件中引起錯(cuò)誤。
- 初始化:靜態(tài)全局變量只初始化一次,防止在其他文件中使用。
const、define宏定義、typedef、inline
const作用及用法
作用:
- const 修飾成員變量,定義成 const 常量,相較于宏常量,可進(jìn)行類(lèi)型檢查,節(jié)省內(nèi)存空間,提高了效率。
- const 修飾函數(shù)參數(shù),使得傳遞過(guò)來(lái)的函數(shù)參數(shù)的值不能改變。
- const 修飾成員函數(shù),使得成員函數(shù)不能修改任何類(lèi)型的成員變量(mutable 修飾的變量除外),也不能調(diào)用非 const 成員函數(shù),因?yàn)榉?const 成員函數(shù)可能會(huì)修改成員變量。
在類(lèi)中的用法:
const 成員變量:
- const 成員變量只能在類(lèi)內(nèi)聲明、定義,在構(gòu)造函數(shù)初始化列表中初始化。
- const 成員變量只在某個(gè)對(duì)象的生存周期內(nèi)是常量,對(duì)于整個(gè)類(lèi)而言卻是可變的,因?yàn)轭?lèi)可以創(chuàng)建多個(gè)對(duì)象,不同類(lèi)的 const 成員變量的值是不同的。因此不能在類(lèi)的聲明中初始化 const 成員變量,類(lèi)的對(duì)象還沒(méi)有創(chuàng)建,編譯器不知道他的值。
const 成員函數(shù):
不能修改成員變量的值,除非有 mutable 修飾;只能訪(fǎng)問(wèn)成員變量。
不能調(diào)用非常量成員函數(shù),以防修改成員變量的值。
define和const的區(qū)別
區(qū)別:
- 編譯階段:define 是在編譯預(yù)處理階段進(jìn)行替換,const 是在編譯階段確定其值。
- 安全性:define 定義的宏常量沒(méi)有數(shù)據(jù)類(lèi)型,只是進(jìn)行簡(jiǎn)單的替換,不會(huì)進(jìn)行類(lèi)型安全的檢查;const 定義的常量是有類(lèi)型的,是要進(jìn)行判斷的,可以避免一些低級(jí)的錯(cuò)誤。
- 內(nèi)存占用:define 定義的宏常量,在程序中使用多少次就會(huì)進(jìn)行多少次替換,內(nèi)存中有多個(gè)備份,占用的是代碼段的空間;const 定義的常量占用靜態(tài)存儲(chǔ)區(qū)的空間,程序運(yùn)行過(guò)程中只有一份。
- 調(diào)試:define 定義的宏常量不能調(diào)試,因?yàn)樵陬A(yù)編譯階段就已經(jīng)進(jìn)行替換了;const 定義的常量可以進(jìn)行調(diào)試。
const 的優(yōu)點(diǎn):
- 有數(shù)據(jù)類(lèi)型,在定義式可進(jìn)行安全性檢查。
- 可調(diào)式。
- 占用較少的空間。
define和typedef的區(qū)別
-
原理:#define 作為預(yù)處理指令,在編譯預(yù)處理時(shí)進(jìn)行替換操作,不作正確性檢查,只有在編譯已被展開(kāi)的源程序時(shí)才會(huì)發(fā)現(xiàn)可能的錯(cuò)誤并報(bào)錯(cuò)。typedef 是關(guān)鍵字,在編譯時(shí)處理,有類(lèi)型檢查功能,用來(lái)給一個(gè)已經(jīng)存在的類(lèi)型一個(gè)別名,但不能在一個(gè)函數(shù)定義里面使用 typedef 。
-
功能:typedef 用來(lái)定義類(lèi)型的別名,方便使用。#define 不僅可以為類(lèi)型取別名,還可以定義常量、變量、編譯開(kāi)關(guān)等。
-
作用域:#define 沒(méi)有作用域的限制,只要是之前預(yù)定義過(guò)的宏,在以后的程序中都可以使用,而 typedef 有自己的作用域。
-
指針的操作:typedef 和 #define 在處理指針時(shí)不完全一樣
用宏實(shí)現(xiàn)比大小
#include <iostream> #define MAX(X, Y) ((X)>(Y)?(X):(Y)) #define MIN(X, Y) ((X)<(Y)?(X):(Y)) using namespace std;int main () {int var1 = 10, var2 = 100;cout << MAX(var1, var2) << endl;cout << MIN(var1, var2) << endl;return 0; } /* 程序運(yùn)行結(jié)果: 100 10 */inline作用及使用方法
作用:
inline 是一個(gè)關(guān)鍵字,可以用于定義內(nèi)聯(lián)函數(shù)。內(nèi)聯(lián)函數(shù),像普通函數(shù)一樣被調(diào)用,但是在調(diào)用時(shí)并不通過(guò)函數(shù)調(diào)用的機(jī)制而是直接在調(diào)用點(diǎn)處展開(kāi),這樣可以大大減少由函數(shù)調(diào)用帶來(lái)的開(kāi)銷(xiāo),從而提高程序的運(yùn)行效率。
使用方法:
類(lèi)內(nèi)定義成員函數(shù)默認(rèn)是內(nèi)聯(lián)函數(shù)
在類(lèi)內(nèi)定義成員函數(shù),可以不用在函數(shù)頭部加 inline 關(guān)鍵字,因?yàn)榫幾g器會(huì)自動(dòng)將類(lèi)內(nèi)定義的函數(shù)(構(gòu)造函數(shù)、析構(gòu)函數(shù)、普通成員函數(shù)等)聲明為內(nèi)聯(lián)函數(shù),代碼如下:
#include <iostream> using namespace std;class A{ public:int var;A(int tmp){ var = tmp;} void fun(){ cout << var << endl;} };int main() { return 0; }類(lèi)外定義成員函數(shù),若想定義為內(nèi)聯(lián)函數(shù),需用關(guān)鍵字聲明
當(dāng)在類(lèi)內(nèi)聲明函數(shù),在類(lèi)外定義函數(shù)時(shí),如果想將該函數(shù)定義為內(nèi)聯(lián)函數(shù),則可以在類(lèi)內(nèi)聲明時(shí)不加 inline 關(guān)鍵字,而在類(lèi)外定義函數(shù)時(shí)加上 inline 關(guān)鍵字。
#include <iostream> using namespace std;class A{ public:int var;A(int tmp){ var = tmp;} void fun(); };inline void A::fun(){cout << var << endl; }int main() { return 0; }另外,可以在聲明函數(shù)和定義函數(shù)的同時(shí)加上 inline;也可以只在函數(shù)聲明時(shí)加 inline,而定義函數(shù)時(shí)不加 inline。只要確保在調(diào)用該函數(shù)之前把 inline 的信息告知編譯器即可。
inline函數(shù)工作原理
- 內(nèi)聯(lián)函數(shù)不是在調(diào)用時(shí)發(fā)生控制轉(zhuǎn)移關(guān)系,而是在編譯階段將函數(shù)體嵌入到每一個(gè)調(diào)用該函數(shù)的語(yǔ)句塊中,編譯器會(huì)將程序中出現(xiàn)內(nèi)聯(lián)函數(shù)的調(diào)用表達(dá)式用內(nèi)聯(lián)函數(shù)的函數(shù)體來(lái)替換。
- 普通函數(shù)是將程序執(zhí)行轉(zhuǎn)移到被調(diào)用函數(shù)所存放的內(nèi)存地址,當(dāng)函數(shù)執(zhí)行完后,返回到執(zhí)行此函數(shù)前的地方。轉(zhuǎn)移操作需要保護(hù)現(xiàn)場(chǎng),被調(diào)函數(shù)執(zhí)行完后,再恢復(fù)現(xiàn)場(chǎng),該過(guò)程需要較大的資源開(kāi)銷(xiāo)。
宏定義(define)和內(nèi)聯(lián)函數(shù)(inline)的區(qū)別
new/delete和malloc/free
new的作用
new 是 C++ 中的關(guān)鍵字,用來(lái)動(dòng)態(tài)分配內(nèi)存空間,實(shí)現(xiàn)方式如下:
int *p = new int[5];new和malloc分別如何判斷是否申請(qǐng)到內(nèi)存
- malloc :成功申請(qǐng)到內(nèi)存,返回指向該內(nèi)存的指針;分配失敗,返回 NULL 指針。
- new :內(nèi)存分配成功,返回該對(duì)象類(lèi)型的指針;分配失敗,拋出 bac_alloc 異常。
delete 實(shí)現(xiàn)原理?delete 和 delete[] 的區(qū)別?
delete 的實(shí)現(xiàn)原理:
- 首先執(zhí)行該對(duì)象所屬類(lèi)的析構(gòu)函數(shù);
- 進(jìn)而通過(guò)調(diào)用 operator delete 的標(biāo)準(zhǔn)庫(kù)函數(shù)來(lái)釋放所占的內(nèi)存空間。
delete 和 delete [] 的區(qū)別:
- delete 用來(lái)釋放單個(gè)對(duì)象所占的空間,只會(huì)調(diào)用一次析構(gòu)函數(shù);
- delete [] 用來(lái)釋放數(shù)組空間,會(huì)對(duì)數(shù)組中的每個(gè)成員都調(diào)用一次析構(gòu)函數(shù)。
new和malloc的區(qū)別
在使用的時(shí)候 new、delete 搭配使用,malloc、free 搭配使用。
- malloc、free 是庫(kù)函數(shù),而 new、delete 是關(guān)鍵字。
- new 申請(qǐng)空間時(shí),無(wú)需指定分配空間的大小,編譯器會(huì)根據(jù)類(lèi)型自行計(jì)算;malloc 在申請(qǐng)空間時(shí),需要確定所申請(qǐng)空間的大小。
- new 申請(qǐng)空間時(shí),返回的類(lèi)型是對(duì)象的指針類(lèi)型,無(wú)需強(qiáng)制類(lèi)型轉(zhuǎn)換,是類(lèi)型安全的操作符;malloc 申請(qǐng)空間時(shí),返回的是 void* 類(lèi)型,需要進(jìn)行強(qiáng)制類(lèi)型的轉(zhuǎn)換,轉(zhuǎn)換為對(duì)象類(lèi)型的指針。
- new 分配失敗時(shí),會(huì)拋出 bad_alloc 異常,malloc 分配失敗時(shí)返回空指針。
- 對(duì)于自定義的類(lèi)型,new 首先調(diào)用 operator new() 函數(shù)申請(qǐng)空間(底層通過(guò) malloc 實(shí)現(xiàn)),然后調(diào)用構(gòu)造函數(shù)進(jìn)行初始化,最后返回自定義類(lèi)型的指針;delete 首先調(diào)用析構(gòu)函數(shù),然后調(diào)用 operator delete() 釋放空間(底層通過(guò) free 實(shí)現(xiàn))。malloc、free 無(wú)法進(jìn)行自定義類(lèi)型的對(duì)象的構(gòu)造和析構(gòu)。
- new 操作符從自由存儲(chǔ)區(qū)上為對(duì)象動(dòng)態(tài)分配內(nèi)存,而 malloc 函數(shù)從堆上動(dòng)態(tài)分配內(nèi)存。(自由存儲(chǔ)區(qū)不等于堆)
(下表來(lái)自:C/C++——C++中new與malloc的10點(diǎn)區(qū)別)
| 分配內(nèi)存的位置 | 自由存儲(chǔ)區(qū) | 堆 |
| 內(nèi)存分配失敗返回值 | 完整類(lèi)型指針 | void* |
| 內(nèi)存分配失敗返回值 | 默認(rèn)拋出異常 | 返回NULL |
| 分配內(nèi)存的大小 | 由編譯器根據(jù)類(lèi)型計(jì)算得出 | 必須顯式指定字節(jié)數(shù) |
| 處理數(shù)組 | 有處理數(shù)組的new版本new[] | 需要用戶(hù)計(jì)算數(shù)組的大小后進(jìn)行內(nèi)存分配 |
| 已分配內(nèi)存的擴(kuò)充 | 無(wú)法直觀地處理 | 使用realloc簡(jiǎn)單完成 |
| 是否相互調(diào)用 | 可以,看具體的operator new/delete實(shí)現(xiàn) | 不可調(diào)用new |
| 分配內(nèi)存時(shí)內(nèi)存不足 | 客戶(hù)能夠指定處理函數(shù)或重新制定分配器 | 無(wú)法通過(guò)用戶(hù)代碼進(jìn)行處理 |
| 函數(shù)重載 | 允許 | 不允許 |
| 構(gòu)造函數(shù)與析構(gòu)函數(shù) | 調(diào)用 | 不調(diào)用 |
- malloc給你的就好像一塊原始的土地,你要種什么需要自己在土地上來(lái)播種
- 而new幫你劃好了田地的分塊(數(shù)組),幫你播了種(構(gòu)造函數(shù)),還提供其他的設(shè)施給你使用:
malloc 的原理?malloc 的底層實(shí)現(xiàn)?
malloc 的原理:
- 當(dāng)開(kāi)辟的空間小于 128K 時(shí),調(diào)用 brk() 函數(shù),通過(guò)移動(dòng) _enddata 來(lái)實(shí)現(xiàn);
- 當(dāng)開(kāi)辟空間大于 128K 時(shí),調(diào)用 mmap() 函數(shù),通過(guò)在虛擬地址空間中開(kāi)辟一塊內(nèi)存空間來(lái)實(shí)現(xiàn)。
malloc 的底層實(shí)現(xiàn):
- brk() 函數(shù)實(shí)現(xiàn)原理:向高地址的方向移動(dòng)指向數(shù)據(jù)段的高地址的指針 _enddata。
- mmap 內(nèi)存映射原理:
- 進(jìn)程啟動(dòng)映射過(guò)程,并在虛擬地址空間中為映射創(chuàng)建虛擬映射區(qū)域;
- 調(diào)用內(nèi)核空間的系統(tǒng)調(diào)用函數(shù) mmap(),實(shí)現(xiàn)文件物理地址和進(jìn)程虛擬地址的一一映射關(guān)系;
- 進(jìn)程發(fā)起對(duì)這片映射空間的訪(fǎng)問(wèn),引發(fā)缺頁(yè)異常,實(shí)現(xiàn)文件內(nèi)容到物理內(nèi)存(主存)的拷貝。
class、struct、union
C 和 C++ struct 的區(qū)別?
- 在 C 語(yǔ)言中 struct 是用戶(hù)自定義數(shù)據(jù)類(lèi)型;在 C++ 中 struct 是抽象數(shù)據(jù)類(lèi)型,支持成員函數(shù)的定義。
- C 語(yǔ)言中 struct 沒(méi)有訪(fǎng)問(wèn)權(quán)限的設(shè)置,是一些變量的集合體,不能定義成員函數(shù);C++ 中 struct 可以和類(lèi)一樣,有訪(fǎng)問(wèn)權(quán)限,并可以定義成員函數(shù)。
- C 語(yǔ)言中 struct 定義的自定義數(shù)據(jù)類(lèi)型,在定義該類(lèi)型的變量時(shí),需要加上 struct 關(guān)鍵字,例如:struct A var;,定義 A 類(lèi)型的變量;而 C++ 中,不用加該關(guān)鍵字,例如:A var;
為什么有了 class 還保留 struct?
C++ 是在 C 語(yǔ)言的基礎(chǔ)上發(fā)展起來(lái)的,為了與 C 語(yǔ)言兼容,C++ 中保留了 struct。
struct 和 union 的區(qū)別
說(shuō)明:union 是聯(lián)合體,struct 是結(jié)構(gòu)體。
區(qū)別:
- 聯(lián)合體和結(jié)構(gòu)體都是由若干個(gè)數(shù)據(jù)類(lèi)型不同的數(shù)據(jù)成員組成。使用時(shí),聯(lián)合體只有一個(gè)有效的成員;而結(jié)構(gòu)體所有的成員都有效。
- 對(duì)聯(lián)合體的不同成員賦值,將會(huì)對(duì)覆蓋其他成員的值,而對(duì)于結(jié)構(gòu)體的對(duì)不同成員賦值時(shí),相互不影響。
- 聯(lián)合體的大小為其內(nèi)部所有變量的最大值,按照最大類(lèi)型的倍數(shù)進(jìn)行分配大小;結(jié)構(gòu)體分配內(nèi)存的大小遵循內(nèi)存對(duì)齊原則。
class 和 struct 的異同
- struct 和 class 都可以自定義數(shù)據(jù)類(lèi)型,也支持繼承操作。
- struct 中默認(rèn)的訪(fǎng)問(wèn)級(jí)別是 public,默認(rèn)的繼承級(jí)別也是 public;class 中默認(rèn)的訪(fǎng)問(wèn)級(jí)別是 private,默認(rèn)的繼承級(jí)別也是 private。
- 當(dāng) class 繼承 struct 或者 struct 繼承 class 時(shí),默認(rèn)的繼承級(jí)別取決于 class 或 struct 本身, class(private 繼承),struct(public 繼承),即取決于派生類(lèi)的默認(rèn)繼承級(jí)別。
- class 可以用于定義模板參數(shù),struct 不能用于定義模板參數(shù)。
volatile
valatile的作用?是否具有原子性?
-
volatile 的作用:當(dāng)對(duì)象的值可能在程序的控制或檢測(cè)之外被改變時(shí),應(yīng)該將該對(duì)象聲明為 volatile,告知編譯器不應(yīng)對(duì)這樣的對(duì)象進(jìn)行優(yōu)化。
-
volatile 不具有原子性。
-
volatile 對(duì)編譯器的影響:使用該關(guān)鍵字后,編譯器不會(huì)對(duì)相應(yīng)的對(duì)象進(jìn)行優(yōu)化,即不會(huì)將變量從內(nèi)存緩存到寄存器中,防止多個(gè)線(xiàn)程有可能使用內(nèi)存中的變量,有可能使用寄存器中的變量,從而導(dǎo)致程序錯(cuò)誤。
什么情況下一定要用 volatile, 能否和 const 一起使用?
使用 volatile 關(guān)鍵字的場(chǎng)景:
- 當(dāng)多個(gè)線(xiàn)程都會(huì)用到某一變量,并且該變量的值有可能發(fā)生改變時(shí),需要用 volatile 關(guān)鍵字對(duì)該變量進(jìn)行修飾;
- 中斷服務(wù)程序中訪(fǎng)問(wèn)的變量或并行設(shè)備的硬件寄存器的變量,最好用 volatile 關(guān)鍵字修飾。
volatile 關(guān)鍵字和 const 關(guān)鍵字可以同時(shí)使用,某種類(lèi)型可以既是 volatile 又是 const ,同時(shí)具有二者的屬性。
extern、sizeof、memmove、strcpy、auto雜問(wèn)
extern C 的作用?
當(dāng) C++ 程序 需要調(diào)用 C 語(yǔ)言編寫(xiě)的函數(shù),C++ 使用鏈接指示,即 extern "C" 指出任意非 C++ 函數(shù)所用的語(yǔ)言。
舉例:
// 可能出現(xiàn)在 C++ 頭文件<cstring>中的鏈接指示 extern "C"{int strcmp(const char*, const char*); }sizeof(1==1) 在 C 和 C++ 中分別是什么結(jié)果?
C 語(yǔ)言代碼:
#include<stdio.h>void main(){printf("%d\n", sizeof(1==1)); }/* 運(yùn)行結(jié)果: 4 */C++ 代碼:
#include <iostream> using namespace std;int main() {cout << sizeof(1==1) << endl;return 0; }/* 1 */C語(yǔ)言:
sizeof(1 == 1) === sizeof(1)按照整數(shù)處理,所以是4字節(jié),這里也有可能是8字節(jié)(看操作系統(tǒng))
C++:
因?yàn)橛衎ool 類(lèi)型,sizeof(1 == 1) == sizeof(true) 按照bool類(lèi)型處理,所以是1個(gè)字節(jié)
memmove與memcpy
詳見(jiàn):memmove 和 memcpy的區(qū)別以及處理內(nèi)存重疊問(wèn)題
strcpy 函數(shù)有什么缺陷?
strcpy 函數(shù)的缺陷:strcpy 函數(shù)不檢查目的緩沖區(qū)的大小邊界,而是將源字符串逐一的全部賦值給目的字符串地址起始的一塊連續(xù)的內(nèi)存空間,同時(shí)加上字符串終止符,會(huì)導(dǎo)致其他變量被覆蓋。
#include <iostream> #include <cstring> using namespace std;int main() {int var = 0x11112222;char arr[10];cout << "Address : var " << &var << endl;cout << "Address : arr " << &arr << endl;strcpy(arr, "hello world!");cout << "var:" << hex << var << endl; // 將變量 var 以 16 進(jìn)制輸出cout << "arr:" << arr << endl;return 0; }/* Address : var 0x23fe4c Address : arr 0x23fe42 var:11002164 arr:hello world! */說(shuō)明:從上述代碼中可以看出,變量 var 的后六位被字符串 "hello world!" 的 "d!\0" 這三個(gè)字符改變,這三個(gè)字符對(duì)應(yīng)的 ascii 碼的十六進(jìn)制為:\0(0x00),!(0x21),d(0x64)。
原因:變量 arr 只分配的 10 個(gè)內(nèi)存空間,通過(guò)上述程序中的地址可以看出 arr 和 var 在內(nèi)存中是連續(xù)存放的,但是在調(diào)用 strcpy 函數(shù)進(jìn)行拷貝時(shí),源字符串 "hello world!" 所占的內(nèi)存空間為 13,因此在拷貝的過(guò)程中會(huì)占用 var 的內(nèi)存空間,導(dǎo)致 var 的后六位被覆蓋。
auto 類(lèi)型推導(dǎo)的原理
auto 類(lèi)型推導(dǎo)的原理:
編譯器根據(jù)初始值來(lái)推算變量的類(lèi)型,要求用 auto 定義變量時(shí)必須有初始值。編譯器推斷出來(lái)的 auto 類(lèi)型有時(shí)和初始值類(lèi)型并不完全一樣,編譯器會(huì)適當(dāng)改變結(jié)果類(lèi)型使其更符合初始化規(guī)則。
總結(jié)
- 上一篇: 双流车管所24小时咨询电话?
- 下一篇: 启辰机油滤清器什么作用呢?