欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

目錄

柚子快報(bào)邀請(qǐng)碼778899分享:【C++】初識(shí)C++

柚子快報(bào)邀請(qǐng)碼778899分享:【C++】初識(shí)C++

http://yzkb.51969.com/

【C++】初識(shí)C++

文章概括關(guān)鍵字(C++98)命名空間命名空間的定義命名空間的特性

輸入與輸出C++中的輸入輸出輸入輸出的命名空間

缺省參數(shù)函數(shù)重載引用引用的概念引用的特性引用地使用場(chǎng)景引用做參數(shù)引用做返回值

常引用常引用的倆個(gè)例子

引用與指針的區(qū)別

內(nèi)聯(lián)函數(shù)

文章概括

談?wù)凜++在學(xué)習(xí)前的認(rèn)知,C++是在C的基礎(chǔ)上,容納進(jìn)去了面向?qū)ο蟮木幊趟枷?,并增加了許多有用的庫(kù),以及編程范式等等。所以學(xué)習(xí)C++之前一定對(duì)C有一定的認(rèn)知,一個(gè)好的C++程序員一定會(huì)是一個(gè)優(yōu)秀的C語(yǔ)言程序員。

本章主要介紹:補(bǔ)充C語(yǔ)言語(yǔ)法的不足,以及C++是如何對(duì)C語(yǔ)言程序設(shè)計(jì)不合理地方進(jìn)行優(yōu)化的,比如:作用域方面、IO方面、函數(shù)方面、指針?lè)矫妗⒑攴矫娴鹊?;同時(shí)也為后續(xù)學(xué)習(xí)類和對(duì)象做了鋪墊。

關(guān)鍵字(C++98)

C++有63個(gè)關(guān)鍵字,C語(yǔ)言有32個(gè)關(guān)鍵字。

關(guān)鍵字關(guān)鍵字關(guān)鍵字關(guān)鍵字關(guān)鍵字asmautoboolbreakcasecatchcharclassconstconst_castdeletedodoubledynamic_castelseenumexplicitexportexternfalsefloatgotoifinlineintlongmutablenamespacenewoperatorprivateprotectedreinterpret_castreturnshortsignedsizeofstaticstatic_casestructswitchtemplatethistrytypedeftypeidtypenameunionunsignedusingvirtualvoidvolatilecontinueforpublicthrowwchar_tdefaultfriendregistertruewhile

后續(xù)逐漸了解

命名空間

命名空間的定義

先以C語(yǔ)言舉例: 假設(shè)需要定義一個(gè)全局變量隨機(jī)數(shù)random為10

#include

int rand = 10;

int main(void)

{

printf("%d\n", rand);

return 0;

}

這是可以編譯成功的,但是我們之前有了解過(guò)rand是一個(gè)頭文件stdlib.h的一個(gè)庫(kù)函數(shù),如果我們包含stdlib.h這個(gè)頭文件會(huì)發(fā)生什么?

#include

#include

int rand = 10;

int main(void)

{

printf("%d\n", rand);

return 0;

}

發(fā)生報(bào)錯(cuò),這里可以明顯突出一個(gè)C語(yǔ)言的庫(kù)命名沖突問(wèn)題。

有時(shí)在一個(gè)大的工程中有多個(gè)項(xiàng)目,每個(gè)項(xiàng)目會(huì)由不同的人負(fù)責(zé),這時(shí)也會(huì)難免遇到項(xiàng)目之間的命名問(wèn)題。

總之,C語(yǔ)言命名沖突的問(wèn)題有: 1.庫(kù)命名沖突問(wèn)題 2.項(xiàng)目相互之間命名的沖突

在C++中,存在命名空間namespace可以解決這類型的問(wèn)題。

在講解命名空間前,需要先了解域的概念:域可以看作是一個(gè)作用區(qū)域,域包含類域、命名空間域、局部域、全局域等等

在一般情況下訪問(wèn)時(shí),會(huì)先訪問(wèn)局部域,在局部域中未發(fā)現(xiàn)變量,會(huì)進(jìn)而訪問(wèn)全局域。

假設(shè)在全局域中存在全局變量,同時(shí)在局部域中也存在一個(gè)局部變量,但是想要跳過(guò)局部域直接訪問(wèn)全局域,應(yīng)該如何操作?

int a = 1;

int main(void)

{

int a = 0;

printf("%d\n", ::a);

return 0;

}

這里需要介紹一個(gè)操作符"::",域操作限定符,::a默認(rèn)會(huì)跳過(guò)局部域,訪問(wèn)全局域。

那如果存在命名空間域namespace,其優(yōu)先級(jí)是如何?

int a = 1;

namespace project

{

int a = 2;

}

int main(void)

{

int a = 0;

printf("%d\n", a);

printf("%d\n", ::a);

return 0;

}

由此可見(jiàn),訪問(wèn)變量a,會(huì)先訪問(wèn)局部域——>然后訪問(wèn)全局域——>最后在默認(rèn)情況下,編譯器并不會(huì)主動(dòng)去命名空間域搜索。

想要搜索命名空間域,有倆種方式: 1.展開(kāi)命名空間域

namespace project

{

int a = 2;

}

using namespace project;

int main(void)

{

printf("%d\n", a);

return 0;

}

2.指定訪問(wèn)命名空間域

namespace project

{

int a = 2;

}

int main(void)

{

printf("%d\n", project::a);

return 0;

}

如果在局部域,全局域,命名空間域(展開(kāi)命名空間域)中都存在變量a,會(huì)如何訪問(wèn)?

這里可以發(fā)現(xiàn)局部域的優(yōu)先級(jí)最高,但如果只存在全局域與展開(kāi)后命名空間域時(shí),會(huì)發(fā)生報(bào)錯(cuò),原因在于:展開(kāi)的命名空間域相當(dāng)于暴露在全局域。

所以不要輕易使用using namespace + 名,即不要請(qǐng)輕易展開(kāi)命名空間域。

總結(jié):在C/C++中,變量、函數(shù)和后面要學(xué)到的類都是大量存在的,這些變量、函數(shù)和類的名稱將都存在于全局作用域中,可能會(huì)導(dǎo)致很多沖突。使用命名空間的目的是對(duì)標(biāo)識(shí)符的名稱進(jìn)行本地化,以避免命名沖突或名字污染,namespace關(guān)鍵字的出現(xiàn)就是針對(duì)這種問(wèn)題的。

命名空間的特性

定義命名空間,需要使用到namespace關(guān)鍵字,后面跟命名空間的名字,然后接一對(duì){}即可,{}中即為命名空間的成員。

namespace project

{

int a = 2;

}

1.命名空間域中可以定義變量、函數(shù)、類型

namespace project

{

//定義變量

int num = 10;

//定義函數(shù)

int add(int x, int y)

{

return x + y;

}

//定義結(jié)構(gòu)體

struct Node

{

struct Node* next;

int data;

};

}

2.命名空間可以嵌套

namespace project

{

namespace N1

{

int a = 1;

}

namespace N2

{

int a = 2;

//定義函數(shù)

int add(int x, int y)

{

return x + y;

}

}

}

int main(void)

{

printf("%d ", project::N1::a);

printf("%d ", project::N2::a);

printf("%d ", project::N2::add(1,2));

return 0;

}

std是C++標(biāo)準(zhǔn)庫(kù)的命名空間名,C++將標(biāo)準(zhǔn)庫(kù)的定義實(shí)現(xiàn)都放在這個(gè)命名空間里。

【注意】:一個(gè)命名空間就定義了一個(gè)新的作用域,命名空間中的所有內(nèi)容都局限于該命名空間中

3.同一個(gè)工程中允許存在多個(gè)相同的命名空間,編譯器最后會(huì)合成同一個(gè)命名空間,即可以在多個(gè)文件中定義相同名字的命名空間

輸入與輸出

C++中的輸入輸出

早年在VC6.0時(shí)沒(méi)有命名空間,頭文件C++中的頭文件

#include

后面改為了

#include

#include

#include

使用iostream這個(gè)頭文件時(shí),需要先學(xué)習(xí)C++的輸入輸出. c語(yǔ)言中使用printf與scanf來(lái)將數(shù)據(jù)輸出與輸入,而在C++中使用cout與cin實(shí)現(xiàn)輸入輸出。

#include

using namespace std;

int main(void)

{

int a;

cin >> a;

cout << a << endl;

return 0;

}

說(shuō)明: 1.使用cout標(biāo)準(zhǔn)輸出對(duì)象(控制臺(tái))和cin標(biāo)準(zhǔn)輸入對(duì)象(鍵盤(pán))時(shí),必須包含頭文件iostream,以及按照命名空間使用方法使用std。 2.cout和cin是全局的流對(duì)象,endl是特殊的C++符號(hào),表示換行輸出,它們都包含在iostream頭文件中 3.<<是流插入運(yùn)算符,>>是流提取運(yùn)算符 4.cout和cin的使用比較方便,不需要同printf與scanf一樣手動(dòng)控制格式,C++的輸入輸出可以手動(dòng)控制變量類型

輸入輸出的命名空間

使用輸入輸出有3種情況: 1.指定訪問(wèn)命名空間域

#include

int main(void)

{

std::cout << "Hello World!" << std::endl;

return 0;

}

2.使用展開(kāi)命名空間域

#include

using namespace std;

int main(void)

{

cout << "Hello World!" << endl;

return 0;

}

編譯器會(huì)去std這個(gè)命名空間搜索(std這個(gè)命名空間域中封有iostream) 【注意】直接展開(kāi)std會(huì)有很大的風(fēng)險(xiǎn),當(dāng)存在自己定義的名字與庫(kù)中名字重合會(huì)報(bào)錯(cuò),建議項(xiàng)目中不要展開(kāi),日常使用可以進(jìn)行展開(kāi),項(xiàng)目中建議指定訪問(wèn),不要輕易展開(kāi)命名空間。

3.展開(kāi)部分命名

#include

using std::cout;

using std::endl;

int main(void)

{

cout << "Hello World!" << endl;

return 0;

}

缺省參數(shù)

缺省參數(shù)也稱默認(rèn)參數(shù),即函數(shù)在傳參的時(shí)候可以存在缺省參數(shù)(默認(rèn)參數(shù))。

void Init(int* node, int sz = 4)

{

int* newnode = (int*)malloc(sizeof(int) * sz);

if (newnode == NULL)

{

perror("malloc fail");

return;

}

node = newnode;

}

int main(void)

{

int* node;

//默認(rèn)情況下,初始化4個(gè)字節(jié)

Init(node);

//可以指定實(shí)參,初始化100個(gè)字節(jié)

Init(node, 100);

return 0;

}

觀察代碼,在C++中傳參存在倆種情況: 1.沒(méi)有參數(shù)時(shí),使用參數(shù)的默認(rèn)值 2.有任何參數(shù)時(shí),使用指定的實(shí)參 即實(shí)參的優(yōu)先級(jí)最大,當(dāng)不存在實(shí)參時(shí),使用默認(rèn)參數(shù) 【注意】當(dāng)存在多個(gè)缺省參數(shù)時(shí),不允許跳著傳參,只能從左到右順序傳參

#include

using namespace std;

//全缺省

int RetAdd(int a = 1, int b = 2, int c = 3)

{

return a + b + c;

}

int main(void)

{

int sum = RetAdd();

cout << sum << endl;

return 0;

}

#include

using namespace std;

//半缺省

int RetAdd(int a, int b, int c = 3)

{

return a + b + c;

}

int main(void)

{

int sum = RetAdd(1,2);

cout << sum << endl;

return 0;

}

C++中全缺省與半缺省的概念 全缺?。核械膮?shù)都給了缺省值 半缺?。喝笔〔糠謪?shù) 【注意】半缺省參數(shù)必須從右至左依次缺省,切勿間隔缺省

【注意】在使用缺省參數(shù)使用需要注意,聲明與定義不能同時(shí)給缺省值,一般在聲明時(shí)存在缺省值,定義時(shí)不存在缺省值。 如果了解文件的編譯與鏈接可以知道,編譯期間只能看到聲明,鏈接期間可以看到定義

函數(shù)重載

重載的意思是:一詞多義 那么函數(shù)重載:是函數(shù)的一種特殊情況,C++允許在同以作用域中聲明幾個(gè)功能類似的同名函數(shù),這些函數(shù)的形參列表(參數(shù)個(gè)數(shù)、參數(shù)類型、類型順序)不同,常用來(lái)處理實(shí)現(xiàn)功能類似數(shù)據(jù)類型不同的問(wèn)題。

參數(shù)類型不同

#include

using namespace std;

//參數(shù)類型不同

int RetAdd(int a, int b)

{

return a + b;

}

double RetAdd(double a, double b)

{

return a + b;

}

int main(void)

{

cout << RetAdd(1, 2) << endl;

cout << RetAdd(1.5, 2.2) << endl;

return 0;

}

參數(shù)個(gè)數(shù)不同

#include

using namespace std;

//參數(shù)個(gè)數(shù)不同

void Fun()

{

cout << "無(wú)參數(shù)" << endl;

}

void Fun(int a)

{

cout << "有參數(shù)" << endl;

}

int main(void)

{

Fun();

Fun(1);

return 0;

}

類型順序不同

#include

using namespace std;

//類型順序不同

double RetAdd(int a, double b)

{

return a + b;

}

double RetAdd(double a, int b)

{

return a + b;

}

int main(void)

{

cout << RetAdd(1, 2.3) << endl;

cout << RetAdd(1.9, 2) << endl;

return 0;

}

【注意】有三個(gè)不構(gòu)成函數(shù)重載的例子 1.僅返回值不同

2.僅變量名不同

3.不明確的函數(shù)調(diào)用

引用

引用的概念

引用不是新定義一個(gè)變量,而是給已存在變量取一個(gè)別名,編譯器不會(huì)為引起變量開(kāi)辟內(nèi)存空間,它和它的變量共用同一塊內(nèi)存空間。

#include

using namespace std;

int main(void)

{

int a = 10;

int& b = a;

int& c = b;

int& d = a;

printf("%p\n", &a);

printf("%p\n", &b);

printf("%p\n", &c);

printf("%p\n", &d);

return 0;

}

類型& : 引用變量名(對(duì)象名) = 引用實(shí)體

在學(xué)習(xí)C語(yǔ)言階段,想要找到一個(gè)變量,可以使用指針,而在C++中引入了引用的概念,可以大幅度代替指針的作用。

int main(void)

{

int a = 0;

int* pa = &a;

int** ppa = &pa;

printf("%p\n", &a);

printf("%p\n", pa);

printf("%p\n", *ppa);

return 0;

}

引用的特性

1.引用在定義時(shí)必須需要初識(shí)化在這里插入圖片描述 2.一個(gè)變量可以有多個(gè)引體

#include

using namespace std;

int main(void)

{

int a = 10;

int& b = a;

int& c = a;

int& d = a;

return 0;

}

3.引用一旦引用一個(gè)實(shí)體,便不可再引用其他引體

#include

using namespace std;

int main(void)

{

int a = 10;

int x = 20;

int& b = a;

b = x;

cout << b << endl;

return 0;

}

引用地使用場(chǎng)景

引用做參數(shù)

引用做參數(shù)時(shí),可以作為輸出型參數(shù)使用,何為輸出型參數(shù)?

函數(shù)在傳參地時(shí)候,會(huì)傳輸出型參數(shù)或者輸入型參數(shù),輸入型參數(shù)的意思是形參的改變不可以改變實(shí)參,即形參是實(shí)參的一份臨時(shí)拷貝;輸出型參數(shù)的意思是形參的改變要改變實(shí)參。

在C語(yǔ)言中一般使用指針來(lái)做輸出型參數(shù):

//鏈表

typedef struct ListNode

{

int data;

struct ListNode* next;

}PNode;

void LTPushBack(PNode* p, int x);

而在C++中,可以使用引用來(lái)做輸出型參數(shù):

//鏈表

typedef struct ListNode

{

int data;

ListNode* next;

//在C++中可以不寫(xiě)struct

}*PNode;

void LTPushBack(PNode& p, int x);

這段代碼的意思是:定義一個(gè)結(jié)構(gòu)體的指針,引用這個(gè)指針并使用phead作為別名。

引用做參數(shù),同時(shí)也可以提高效率,但是只存在于數(shù)量較大對(duì)象或者深拷貝類對(duì)象。

下面這段代碼可以比較傳值與傳引用的效率對(duì)比:

#include

struct A { int a[100000]; };

void TestFunc1(A a) {}

void TestFunc2(A& a) {}

void TestRefAndValue()

{

A a;

// 以值作為函數(shù)參數(shù)

size_t begin1 = clock();

for (size_t i = 0; i < 10000; ++i)

TestFunc1(a);

size_t end1 = clock();

// 以引用作為函數(shù)參數(shù)

size_t begin2 = clock();

for (size_t i = 0; i < 10000; ++i)

TestFunc2(a);

size_t end2 = clock();

// 分別計(jì)算兩個(gè)函數(shù)運(yùn)行結(jié)束后的時(shí)間

cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;

cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;

}

由于函數(shù)在傳參期間,以值作為參數(shù),函數(shù)不會(huì)之間傳遞實(shí)參或者將變量本身直接返回,而是傳遞實(shí)參的一份臨時(shí)拷貝,因此以值作為參數(shù)時(shí)的效率是很低的,尤其是參數(shù)非常大時(shí),效率會(huì)更低。

對(duì)象越大,代價(jià)就會(huì)越大,提高的效率就越多

【注意】引用相比較于指針沒(méi)有質(zhì)的區(qū)別,但是在C++中實(shí)際情況下引用的使用情況較多。

引用做返回值

int Count()

{

static int n = 0;

n++;

return n;

}

int main(void)

{

int ret = Count();

return 0;

}

觀察這段代碼,使用傳值返回時(shí),會(huì)生成臨時(shí)變量,可能會(huì)存放在寄存器中(寄存器的大小為4/8個(gè)字節(jié),如果寄存器內(nèi)存不夠,會(huì)向上申請(qǐng)),作為int ret = Count();這段代碼的返回值。

雖然n被static int修飾,成為靜態(tài)變量,存放在靜態(tài)區(qū)中,但是不管有沒(méi)有static修飾或者存在全局變量,函數(shù)都會(huì)根據(jù)返回值int,創(chuàng)造出一個(gè)臨時(shí)變量,這樣會(huì)大大降低效率,那么使用引用做返回值可以解決這樣的問(wèn)題。

下面就是引用做返回值的第一個(gè)作用:

減少拷貝,提高效率

int& Count()

{

static int n = 0;

n++;

return n;

}

int main(void)

{

int ret = Count();

return 0;

}

下面這段代碼可以比較傳值返回與傳引用返回:

#include

struct A{ int a[10000]; };

A a;

// 值返回

A TestFunc1() { return a;}

// 引用返回

A& TestFunc2(){ return a;}

void TestReturnByRefOrValue()

{

// 以值作為函數(shù)的返回值類型

size_t begin1 = clock();

for (size_t i = 0; i < 100000; ++i)

TestFunc1();

size_t end1 = clock();

// 以引用作為函數(shù)的返回值類型

size_t begin2 = clock();

for (size_t i = 0; i < 100000; ++i)

TestFunc2();

size_t end2 = clock();

// 計(jì)算兩個(gè)函數(shù)運(yùn)算完成之后的時(shí)間

cout << "TestFunc1 time:" << end1 - begin1 << endl;

cout << "TestFunc2 time:" << end2 - begin2 << endl;

}

由于函數(shù)在傳值返回期間,以值作為返回值,函數(shù)不會(huì)之間傳遞實(shí)參或者將變量本身直接返回,而是返回變量的一份臨時(shí)拷貝,因此以值作為返回值時(shí)的效率是很低的,尤其是參數(shù)非常大時(shí),效率會(huì)更低。

使用引用做返回值,還有另外一個(gè)作用:

修改返回值以及獲取返回值

typedef struct SeqList

{

int arr[100];

int size;

}SL;

int& SLPostion(SL& s, int pos)

{

assert(pos < 100 && pos >= 0);

return s.arr[pos];

}

int main(void)

{

SL s;

SLPostion(s, 0) = 1;

int ret = SLPostion(s, 0);

cout << ret << endl;

cout << SLPostion(s, 0) << endl;

return 0;

}

如果不使用static修飾靜態(tài)變量,使用引用做返回值時(shí),結(jié)果時(shí)不確定的。

int& Count()

{

int n = 0;

n++;

return n;

}

int main(void)

{

int& ret = Count();

cout << ret << endl;

return 0;

}

這段代碼雖然不會(huì)報(bào)錯(cuò),但是明顯可以發(fā)現(xiàn),ret訪問(wèn)是存在越界訪問(wèn)。

int& Count(int n)

{

n++;

return n;

}

int main(void)

{

int& ret = Count(10);

cout << ret << endl;

Count(20);

cout << ret << endl;

return 0;

}

觀察這段代碼,如果count函數(shù)結(jié)束,函數(shù)建立的棧幀會(huì)銷(xiāo)毀,在vs編譯器上沒(méi)有清理?xiàng)瑀et的值是第一次函數(shù)調(diào)用結(jié)束后,第二次函數(shù)建立在同樣的位置。

int& Count(int n)

{

n++;

return n;

}

int main(void)

{

int& ret = Count(10);

cout << ret << endl;

rand();

cout << ret << endl;

return 0;

}

若是隨意插入一個(gè)函數(shù),則ret的值變成了隨機(jī)值。

可以發(fā)現(xiàn),在這種情況下使用引用是很危險(xiǎn)的。

總結(jié): 1.基本任何場(chǎng)景都是可以使用引用傳參 2.謹(jǐn)慎用引用做返回值,出了函數(shù)作用域,對(duì)象不在了就不能使用引用返回,如果對(duì)象還在就可以使用引用返回。 2.可以使用引用返回的場(chǎng)景:靜態(tài)變量、全局變量、堆區(qū)malloc或者calloc

常引用

const int a = 0;

int& b = a;

觀察這段代碼,當(dāng)變量a被const修飾變成不可修改的左值時(shí),使用int引用是不可以的,原因是在引用的過(guò)程中國(guó)權(quán)限不能放大。

int a = 0;

int& b = a;

const int a = 0;

const int& b = a;

這倆種情況是被允許的,這倆種情況是權(quán)限的平移。

int a = 0;

const int& b = a;

這種情況也是被允許的,這種情況被稱為權(quán)限的縮小。

int a = 0;

const int& b = a;

a++;

這種情況也是被允許的,原因是編譯器僅縮小了a和b所在地址的引用b的權(quán)限,而并沒(méi)有縮小a的權(quán)限所有a++是被允許的,而b++是不被允許的。

const int& x = 10;

同時(shí),給變量取別名也是被允許的。

常引用的倆個(gè)例子

double d = 1.11;

int i = d;

我們都知道double在轉(zhuǎn)變?yōu)閕nt時(shí),會(huì)進(jìn)行類型轉(zhuǎn)換,由于double是8個(gè)字節(jié),int是4個(gè)字節(jié),double變成int會(huì)進(jìn)行截?cái)?,而截?cái)嗟倪^(guò)程會(huì)建立一個(gè)新的臨時(shí)變量,臨時(shí)變量具有常性,即臨時(shí)變量是不可修改的值。

double d = 1.11;

int& i = d;

所有這段代碼是錯(cuò)誤的,這里double變成臨時(shí)變量權(quán)限縮小,而int&會(huì)將權(quán)限放大,引用的過(guò)程中權(quán)限是不可以放大的。

double d = 1.11;

const int& i = d;

這段代碼是正確的,這里進(jìn)行了權(quán)限的平移。

int Fun()

{

static int x = 0;

return x;

}

int main(void)

{

int& ret1 = Fun();

const int& ret2 = Fun();

}

第二個(gè)例子是關(guān)于函數(shù)在釋放前會(huì)建立一個(gè)臨時(shí)變量給返回值提供位置。此時(shí)這個(gè)臨時(shí)變量也是具有常性,是不可以修改的,即ret1是錯(cuò)誤的代碼,而ret2是正確的代碼。

引用與指針的區(qū)別

引用與指針在語(yǔ)法層面是不同的,引用不開(kāi)空間,引用是對(duì)變量取別名,而指針不同,指針開(kāi)空間,指針是存儲(chǔ)變量的地址。

int x = 10;

int* y = &x;

int a = 20;

int& b = a;

觀察這段代碼,可以發(fā)現(xiàn)從底層匯編指令實(shí)現(xiàn)的角度來(lái)看,引用是類似指針的方式實(shí)現(xiàn)的。

指針與引用的不同點(diǎn): 1.引用概念上定義一個(gè)變量的別名,而指針存儲(chǔ)一個(gè)變量的地址 2.引用在定義時(shí)必須初始化,而指針沒(méi)有要求 3.引用在初始化時(shí)引用一個(gè)實(shí)體后,就不可以引用其他實(shí)體,而指針可以在任何時(shí)候指向任何一個(gè)同類型的實(shí)體 4.沒(méi)有NULL引用,但有NULL指針 5.引用和指針在sizeof中含義不同,引用結(jié)果為引用類型的大小,而指針始終是地址空間所占字節(jié)個(gè)數(shù)(32位平臺(tái)下占4個(gè)字節(jié)) 6.引用自加即引用的實(shí)體增加1,指針自加即指針向后偏移一個(gè)指針類型的位置 7.有多級(jí)指針,但沒(méi)有多級(jí)引用 8.訪問(wèn)實(shí)體的方式不同,指針需要解引用,引用編譯器會(huì)自己處理 9.引用比指針使用起來(lái)相對(duì)安全

內(nèi)聯(lián)函數(shù)

在了解內(nèi)聯(lián)函數(shù)之前,應(yīng)該對(duì)C語(yǔ)言中的宏的定義有一定了解。

//宏定義

#define ADD(x,y) ((x) + (y)) * 10

//注意規(guī)范,宏定義是完整的替換

int main(void)

{

for (int i = 0; i < 100; i++)

{

cout << ADD(i, i + 1) << endl;

}

return 0;

}

在C語(yǔ)言中,使用宏定義來(lái)解決函數(shù)建立過(guò)多且函數(shù)內(nèi)容較少的問(wèn)題。但是宏在使用過(guò)程中也存在著也許優(yōu)點(diǎn)與缺點(diǎn): 宏函數(shù)的優(yōu)點(diǎn):不需要建立棧幀,提高調(diào)用效率,增強(qiáng)代碼的復(fù)用性 宏函數(shù)的缺點(diǎn):復(fù)雜、容易出錯(cuò);可讀性差;不能調(diào)試。

在C++中,會(huì)使用內(nèi)聯(lián)函數(shù)來(lái)代替部分宏函數(shù)。 以inline修飾的函數(shù)被稱為內(nèi)聯(lián)函數(shù),編譯時(shí)C++編譯器會(huì)根據(jù)情況在調(diào)用內(nèi)聯(lián)函數(shù)的地方進(jìn)行展開(kāi),沒(méi)有函數(shù)調(diào)用建立棧幀的開(kāi)銷(xiāo),內(nèi)聯(lián)函數(shù)提高程序運(yùn)行的速度。

//內(nèi)聯(lián)函數(shù)

inline int Add(int x, int y)

{

return (x + y) * 10;

}

int main(void)

{

for (int i = 0; i < 100; i++)

{

cout << Add(i, i + 1) << endl;

}

return 0;

}

由此可知,宏函數(shù)與內(nèi)聯(lián)函數(shù)是很相似的,但C++對(duì)宏函數(shù)進(jìn)行了優(yōu)化,宏函數(shù)與內(nèi)聯(lián)函數(shù)適用于短小,需要頻繁調(diào)用的函數(shù)。

但是并不是所有的函數(shù)都可以使用內(nèi)聯(lián)函數(shù),否則就會(huì)導(dǎo)致可執(zhí)行程序變大。 這里假設(shè)Func不是內(nèi)聯(lián)函數(shù)(不被inline修飾),每次執(zhí)行Func函數(shù)時(shí)都會(huì)跳轉(zhuǎn)到Func去執(zhí)行,如果存在n個(gè)位置調(diào)用Func函數(shù),則合計(jì)會(huì)有m+n條指令;

這里假設(shè)Func是內(nèi)聯(lián)函數(shù)(被inline修飾),相當(dāng)于每次執(zhí)行Func函數(shù)都會(huì)對(duì)Func進(jìn)行展開(kāi),如果存在n個(gè)位置調(diào)用Func函數(shù),則合計(jì)會(huì)有m*n條指令。

若調(diào)用Func函數(shù)過(guò)多,則會(huì)導(dǎo)致可執(zhí)行程序變大。

編譯器在識(shí)別被inline修飾的內(nèi)聯(lián)函數(shù)時(shí),內(nèi)聯(lián)函數(shù)對(duì)編譯器只是一個(gè)建議,最終時(shí)候成為內(nèi)聯(lián)函數(shù),編譯器會(huì)自己決定,在這些情況下,編譯器會(huì)自動(dòng)否決內(nèi)聯(lián):1.比較長(zhǎng)的函數(shù);2.遞歸函數(shù)。

默認(rèn)在debug版本下,inline不會(huì)起作用,否則無(wú)法支持調(diào)試。在debug版本下,需要對(duì)編譯器進(jìn)行設(shè)置:

這里可以發(fā)現(xiàn),在調(diào)用代碼較少時(shí),此時(shí)內(nèi)聯(lián)函數(shù)起效果;

inline int Add(int x, int y)

{

for (int i = 0; i < 100; i++)

{

x *= 2;

}

for (int i = 0; i < 100; i++)

{

x /= 2;

}

for (int i = 0; i < 100; i++)

{

y *= 2;

}

for (int i = 0; i < 100; i++)

{

y /= 2;

}

return x + y;

}

int main(void)

{

int ret = Add(1, 2);

return 0;

}

此時(shí),函數(shù)內(nèi)容過(guò)多,內(nèi)聯(lián)函數(shù)被編譯器否決;

inline int Add(int x,int y)

{

if (x > 5 && y > 5)

return x + y;

return Add(x + 1, y + 1);

}

int main(void)

{

int ret = Add(1, 2);

cout << ret << endl;

return 0;

}

此時(shí),函數(shù)遞歸,內(nèi)聯(lián)函數(shù)被編譯器否決;

//Func.h文件

inline int Add(int x, int y);

//Func.cpp文件

#include"Func.h"

inline int Add(int x, int y)

{

return (x + y) * 10;

}

//test.cpp文件

#include

#include"Func.h"

using namespace std;

int main(void)

{

int ret = Add(1, 2);

cout << ret << endl;

return 0;

}

如果內(nèi)聯(lián)函數(shù)沒(méi)有被編譯器否決,那么內(nèi)聯(lián)函數(shù)就會(huì)在編譯期間會(huì)被展開(kāi),建議內(nèi)聯(lián)函數(shù)聲明與定義不分離,直接寫(xiě)在頭文件中。 原因是,內(nèi)聯(lián)函數(shù)不會(huì)被call,所有內(nèi)聯(lián)函數(shù)就不會(huì)進(jìn)入符號(hào)表進(jìn)行鏈接,如果聲明與定義分離,會(huì)導(dǎo)致鏈接錯(cuò)誤,內(nèi)聯(lián)函數(shù)被展開(kāi)后尋找不到函數(shù)地址,鏈接就會(huì)找不到。

柚子快報(bào)邀請(qǐng)碼778899分享:【C++】初識(shí)C++

http://yzkb.51969.com/

參考鏈接

評(píng)論可見(jiàn),查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。

轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19024363.html

發(fā)布評(píng)論

您暫未設(shè)置收款碼

請(qǐng)?jiān)谥黝}配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問(wèn)

文章目錄