做網(wǎng)站必須要購買空間嗎谷歌瀏覽器 免費(fèi)下載
在這篇博客中,我將會介紹從C語言過渡到C++的一些基礎(chǔ)知識。
目錄
C++起源
C++的關(guān)鍵字
輸出hello,world
?編輯
命名空間
1.什么是命名空間
2.namespace的作用
3.域作用限定符
4.命名空間的使用
IO流
缺省參數(shù)
函數(shù)重載
引用
1.引用的定義
2.引用的特性
3.引用的使用
4.const引用
5.引用和指針
內(nèi)聯(lián)函數(shù)inline
nullptr
C++起源
在1979年,本賈尼·斯特勞斯特盧普在貝爾實(shí)驗(yàn)室中進(jìn)行復(fù)雜的軟件開發(fā)時,他感受到了C語言的局限性,于是他在此基礎(chǔ)上設(shè)計(jì)了C++。
C++在C語言的基礎(chǔ)上添加了面向?qū)ο缶幊痰奶匦?封裝、繼承、多態(tài)。
隨后幾年,C++不斷完善發(fā)展,在1998年推出了C++98,官方第一個較為完善的版本,引入了STL(標(biāo)準(zhǔn)模板庫)。
在2011年,C++的一次革命性的更新,增加了大量特性和功能。
在2020年,C++又一次巨大更新,引入了模板(Modules)、概念(Concepts)、協(xié)程(Coroutines)等
在公司中,使用的比較多的都是C++98和C++11.
C++的關(guān)鍵字
輸出hello,world
#include<iostream>
using namespace std;int main()
{cout << "hello,world!" << endl;return 0;
}
命名空間
1.什么是命名空間
命名空間需要用一個關(guān)鍵字namespace,后跟命名空間的名字,然后用{}括起來,在里面可以定義變量、函數(shù)、自定義類型,即為命名空間的成員。
2.namespace的作用
在C/C++中,變量、函數(shù)、類是大量存在的,這些名稱在全局域中可能會重復(fù)從而引發(fā)沖突。
#include<stdlib.h>
int rand = 15;int main()
{//這里會報(bào)編譯錯誤,“rand” : 重定義;以前的定義是“函數(shù)” printf("%d\n", rand);return 0;
}
C++中域有函數(shù)局部域,全局域,命名空間域,類域。局部域和全局域除了會影響編譯查找邏輯,還會影響變量的生命周期,命名空間域和類域不影響變量生命周期。
namespace會定義一個域,也就是命名空間域,它與全局域獨(dú)立,不同的域可以存在同名變量。
我們可以將rand放于一個命名空間域,從而修正上述問題。
namespace只能定義在全局,當(dāng)然他還可以嵌套定義。
項(xiàng)目工程中多文件中定義的同名namespace會認(rèn)為是?個同namespace,不會沖突。
3.域作用限定符
既然有不同的有不同的域,那我們可以通過域作用限定符(::)l來訪問域中的成員變量。
::默認(rèn)訪問全局域;在其左側(cè)加上域名就是訪問該名字的域,如上面代碼,Moss::rand就時訪問的Moss域中的rand變量。
4.命名空間的使用
namespace的使用主要分為兩種:
1.指定命名空間訪問,實(shí)際項(xiàng)目中推薦這種。
2.使用關(guān)鍵字using將命名空間的某個成員或者全部成員展開
C++標(biāo)準(zhǔn)庫都放在?個叫std(standard)的命名空間中。
#include<iostream>
using namespace std;//展開std中的所有成員
IO流
IO流其實(shí)就是輸入輸出流,與之相關(guān)的頭文件就是<iostream>。
<iostream>:Input Output Stream,標(biāo)準(zhǔn)輸入輸出流庫,定義了標(biāo)準(zhǔn)輸入輸出對象。
std標(biāo)準(zhǔn)庫就被包含在其中。
cout、cin、endl都屬于C++標(biāo)準(zhǔn)庫(std)
cout:用于屏幕輸出
cin:用于鍵盤輸入
endl:輸出時,增加換行符('\n')
<<是流插入運(yùn)算符,>>是流提取運(yùn)算符。(在C語言是左移/右移運(yùn)算符)。
cout和cin的輸出輸入通過函數(shù)重載實(shí)現(xiàn)自動識別變量類型,無須像C語言那樣指定格式。
使用格式如下:
缺省參數(shù)
缺省參數(shù)就是在聲明或者定義函數(shù)時,為函數(shù)的實(shí)參指定一個默認(rèn)值,無參數(shù)調(diào)用函數(shù)時,函數(shù)就會使用該默認(rèn)值。
需要注意的幾個點(diǎn):
1.當(dāng)函數(shù)聲明和定義分離時,缺省參數(shù)只能在函數(shù)聲明出現(xiàn),函數(shù)定義不能使用缺省參數(shù)。
2.缺省參數(shù)的指定在函數(shù)的聲明或者定義中,規(guī)定缺省參數(shù)必須從右往左依次指定,不能跳躍給缺省參數(shù)。
3.對于帶缺省參數(shù)的函數(shù)調(diào)用,從左往右依次傳實(shí)參,不能跳躍傳。
4.全缺省:全部形參給缺省值。
半缺省:部分形參給缺省值。
函數(shù)重載
函數(shù)重載:同一作用域中出現(xiàn)同名函數(shù),但是這些函數(shù)的形參各不相同。
函數(shù)重載允許返回值的類型相等,但是返回值的類型不同 不能作為函數(shù)重載的標(biāo)識。
1.參數(shù)類型不同
2.參數(shù)個數(shù)不同
3參數(shù)類型順序不同
接下來我們看一個需要警惕的坑:
上面這兩個函數(shù)構(gòu)成函數(shù)重載,因?yàn)閰?shù)個數(shù)不同,但是這兩個函數(shù)存在調(diào)用歧義,調(diào)用F()函數(shù)時,編譯器不知道調(diào)用哪個函數(shù)。
引用
1.引用的定義
引用:給一個存在變量取別名,引用變量與原變量共用一塊內(nèi)存空間。
語法形式:類型& 引用的別名 = 引用對象
這里a、b、c、d都是共用一塊內(nèi)存空間的
2.引用的特性
1.引用的變量必須初始化。
2.一個變量可以多個引用。
3.引用一旦引用了一個變量,就不得再引用其他變量。(引用的指向不允許更改)
int a = 5;//編譯錯: ra必須初始化引用
//int& ra;int& b = a;int c = 10;
//這里是賦值,將c的值賦給b(a),不是改變引用的指向
b = c;
3.引用的使用
1.引用傳參
2.做返回值
引用傳參:
引用傳參表面上是傳值,但實(shí)際上傳的是地址,只不過是編譯器幫做了。
void Swap(int& x, int& y)//引用傳參 可以替換 傳址調(diào)用
{int tmp = x;x = y;y = tmp;
}
4.const引用
當(dāng)引用一個const對象時,必須const引用,否則就會權(quán)限放大,權(quán)限不允許放大,但可以縮小。
const int a = 10;
//權(quán)限不能放大,必須用const引用
//int& ra = a;
const int& ra = a;int b = 5;
//權(quán)限縮小是可以的
const int& rb = b;
臨時對象:編譯器在一塊空間暫存表達(dá)式的結(jié)果時臨時創(chuàng)建的未命名的對象。
臨時對象的引用:臨時對象具有常性,也必須用const引用。(不用const引用就會觸發(fā)權(quán)限放大,然后就報(bào)錯)
int a = 4;
const int& ra = a * 3;//a * 3的結(jié)果存放在臨時變量中,得用const引用double d = 3.14;
const int& rd = d;//類型轉(zhuǎn)換產(chǎn)生的中間值也存放在臨時變量中,也得用const引用
5.引用和指針
1.引用必須初始化,不開空間;指針存儲變量地址,語法上可以不初始化(nullptr),但是要開空間
2.引用的指向不能改變,而指針可以隨意更改。
3.引用直接訪問對象,指針要解引用。
4.sizeof的結(jié)果不同,引用結(jié)果為類型大小,但指針只跟多少位系統(tǒng)有關(guān)(32位4個字節(jié),64位8個字節(jié))
5.使用引用相對安全,指針容易出現(xiàn)空指針和野指針的問題。
內(nèi)聯(lián)函數(shù)inline
定義:用inline修飾的函數(shù)就是內(nèi)聯(lián)函數(shù)
作用:內(nèi)聯(lián)函數(shù)在調(diào)用的時候,編譯器會在調(diào)用的地方展開內(nèi)聯(lián)函數(shù),這樣就不需要建立函數(shù)棧幀,以便提高效率。
所以我們通過作用就很容易想到,內(nèi)聯(lián)函數(shù)設(shè)計(jì)出來是為了代替C語言的宏函數(shù),而替代的原因是宏函數(shù)的實(shí)現(xiàn)很容易出錯。
//正確的宏實(shí)現(xiàn)
#define ADD(x, y) ((x) + (y))
// 為什么不能加分號?
// 為什么要加外面的括號?
// 為什么要加里面的括號?
//保證優(yōu)先級
int main()
{cout << ADD(1, 2) * 5 << endl;int x = 1, y = 2;ADD(x & y, x | y);// ->(x&y + x|y)//+的優(yōu)先級比& | 高,所以里面也要加括號return 0;
}
需要注意的點(diǎn):
1.inline對于編譯器只是建議,并不是說加了一定會在調(diào)用的地方被展開,一般來說,inline適用于簡短而又被頻繁調(diào)用的函數(shù),對于代碼較多的函數(shù),加了inline也會被編譯器忽略。
2.inline不推薦函數(shù)聲明和定義分離到兩個文件,如果inline函數(shù)被展開,鏈接時就會報(bào)錯。
?vs編譯器在debug版本下默認(rèn)不展開inline,以便調(diào)試。
nullptr
在C語言中,空指針NULL實(shí)際上是一個宏
NULL的使用不可避免存在一定的問題,本想調(diào)用指針版本的F(int* ptr),但是NULL被定義成0,從而調(diào)用了F(int x)版本,這有違初衷。
因此在C++中新增關(guān)鍵字nullptr,它可以轉(zhuǎn)換任意類型的指針類型。
nullptr只能被隱式轉(zhuǎn)換為指針類型,不能轉(zhuǎn)換為整數(shù)類型,所以nullptr定義空指針可以避免類型轉(zhuǎn)換。
拜拜,下期再見😏
摸魚ing😴?🎞