C++的初步學(xué)習(xí)有以下幾個(gè)方面
成都創(chuàng)新互聯(lián)公司專注于長(zhǎng)沙縣企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站開發(fā),成都商城網(wǎng)站開發(fā)。長(zhǎng)沙縣網(wǎng)站建設(shè)公司,為長(zhǎng)沙縣等地區(qū)提供建站服務(wù)。全流程按需制作,專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,成都創(chuàng)新互聯(lián)公司專業(yè)和態(tài)度為您提供的服務(wù)我們知道,在c中有32個(gè)關(guān)鍵字,而c++中有63個(gè)關(guān)鍵字
分別為
為什么會(huì)有命名空間,他的作用是什么?
在一個(gè)大的工程里,要定義很多變量和函數(shù),若將這些變量和函數(shù)都定義在全局作用域中,一不小心就可能出現(xiàn)重復(fù)定義的情況。因而引入命名空間的概念,其目的是對(duì)標(biāo)識(shí)符名稱進(jìn)行本地化,以避免命名沖突或名字沖突。
命名空間是什么?
一個(gè)命名空間就定義了一個(gè)新的作用域,命名空間中的所有內(nèi)容都局限于該命名空間里。命名空間里可有變量、函數(shù)、結(jié)構(gòu)體、另一個(gè)命名空間等等普通在全局定義的命名空間里都可以有。在不同的命名空間里可以使用一個(gè)變量名。以后在使用某個(gè)命名空間里的某個(gè)變量,引入就可以了。這樣定義變量時(shí),就不用考慮之前這個(gè)名字有沒有用過,只用看在這個(gè)命名空間里存不存在該變量。
命名空間的定義
定義命名空間,需要使用到namespace關(guān)鍵字,后面跟命名空間的名字,然后接一對(duì){}即可,{}中即為命名空間的成員。命名空間的定義有以下三種形式:
//1.普通定義
namespace N1 // N1為命名空間的名稱
{
int a;
int Add(int left, int right)
{
return left + right;
}
}
//2.嵌套定義
namespace N2
{
int a;
int b;
int Add(int left, int right)
{
return left + right;
}
namespace N3
{
int c;
int d;
int Sub(int left, int right)
{
return left - right;
}
}
}
//3.重復(fù)的定義
namespace N1{int a};
namespace N1{int b};
//在編譯時(shí),編譯器會(huì)自動(dòng)將其合并為一個(gè)命名空間,在定義的時(shí)候也可將其看做同一個(gè)命名空間,因而同名命名空間不要使用相同變量
命名空間的使用
在命名空間里定義的內(nèi)容是不可以直接使用的。
引用一個(gè)操作符 ‘::’ 作用域限定符用于在作用域外引用作用域里的內(nèi)容
引用一個(gè)關(guān)鍵字:在一個(gè)作用域中使用 using 將另一個(gè)命名空間里的想要的內(nèi)容拿出來,方便下面使用
使用方式有以下三種:
//1.加命名空間名稱及作用域限定符
namespace N
{
int a;
int b;
}
int main{
printf("%d\n", N::a); 打印N中的a
return 0;
}
//2.使用using將命名空間中成員引入
using N::b;
int main()
{
printf("%d\n", N::a); //并沒引入a
printf("%d\n", b); //在此的b就可以直接使用了
return 0;
}
// 3.使用using namespace 命名空間名稱引入
using namespce N; //將N 中所有的內(nèi)容都引入
int main()
{
printf("%d\n", a);
printf("%d\n", b);
return 0;
}
輸出函數(shù):cout標(biāo)準(zhǔn)輸出(控制臺(tái))類似于printf
輸入函數(shù):cin標(biāo)準(zhǔn)輸入(鍵盤)類似于scanf
兩個(gè)函數(shù)屬于標(biāo)準(zhǔn)庫 iostream 再引入命名空間std
用法:他們的用法比printf和scanf要靈活,輸出不用再加%d..來說明輸出/輸入什么類型的值,可連接各種類型的值
例如如下代碼
#include
using namespace std;
int main()
{
int a;
double b;
char c;
cin>>a;
cin>>b>>c;
cout<
概念:缺省參數(shù)是聲明或定義函數(shù)時(shí)為函數(shù)的參數(shù)指定一個(gè)默認(rèn)值。在調(diào)用該函數(shù)時(shí),如果沒有指定實(shí)參則采用該默認(rèn)值,否則使用指定的實(shí)參。例如:
void TestFunc(int a = 0)
{
cout<
在一個(gè)函數(shù)的形參列表中,我們可以給一部分形參默認(rèn)值,也可以全給。因此分為半缺省參數(shù)和全缺省參數(shù),用法及要求如下
全缺省參數(shù):每個(gè)形參都賦了缺省值
void TestFunc(int a = 10, int b = 20, int c = 30)
{
cout<<"a = "<
半缺省參數(shù):不是所有的形參都賦了缺省值,但賦半缺省參數(shù)有一定規(guī)則: 半缺省參數(shù)必須從右往左依次來給出,不能間隔著給,就是前面的可以省略,但一旦給值,后面的都必須都給值 。因此
void TestFunc(int a, int b = 10, int c = 20)√
void TestFunc(int a=10, int b , int c = 20) ×
void TestFunc(int a=10, int b=20 , int c ) ×
通過半缺省參數(shù)的規(guī)則,我們可回答為什么全缺省參數(shù)給值是從前往后給的:半缺省參數(shù)前面的可以省略,所以在不知道函數(shù)是不是半缺省參數(shù)的情況下,實(shí)參要賦從第一個(gè)形參開始賦值
定義:在同一作用域中聲明幾個(gè)功能類似的同名函數(shù),這些同名函數(shù)的形參列表(參數(shù)個(gè)數(shù) 或 類型 或 順序)必須不同,常用來處理實(shí)現(xiàn)功能類似數(shù)據(jù)類型不同的問題。
如以下代碼:
int Add(int left, int right)
{
return left+right;
}
double Add(double left, double right)
{
return left+right;
}
long Add(long left, long right)
{
return left+right;
}
int main()
{
Add(10, 20);
Add(10.0, 20.0);
Add(10L, 20L); //通過實(shí)參類型來找函數(shù)
return 0;
}
注:函數(shù)不可僅靠返回值類型來實(shí)現(xiàn)重載
short Add(short left, short right)
{
return left+right;
}
int Add(short left, short right)
{
return left+right;
}
//這兩個(gè)函數(shù)無法實(shí)現(xiàn)重載
void TestFunc(int a = 10);
void TestFunc( );
//這兩個(gè)函數(shù)就無法形成重載,在另一個(gè)函數(shù)中調(diào)用TestFunc( ),編譯器不知道要調(diào)用哪一個(gè);
缺省函數(shù)與普通函數(shù)無法形成重載,例如:
void TestFunc(int a = 10);
void TestFunc(int a );
//這兩個(gè)函數(shù)就無法形成重載,在另一個(gè)函數(shù)中調(diào)用TestFunc(num ),編譯器不知道要調(diào)用哪一個(gè);
因而:想要形成函數(shù)重載,要確保兩個(gè)函數(shù)在調(diào)用的時(shí)候不會(huì)起沖突,不會(huì)出現(xiàn)在傳某個(gè)值的時(shí)候,兩個(gè)函數(shù)都可以調(diào)的情況。
我們知道:c語言中不可以實(shí)現(xiàn)函數(shù)重載,為什么c++中可以呢?因?yàn)樵诔绦蚓幾g時(shí),編譯器會(huì)對(duì)每個(gè)函數(shù)名進(jìn)行命名修飾,下面我們來引入命名修飾的概念
在c++程序編譯時(shí),編譯器為區(qū)分各個(gè)函數(shù),會(huì)將函數(shù)、變量名重新改變,使每個(gè)函數(shù)名成為全局唯一的名稱,將參數(shù)類型包含在最終的名字中,因而通過形參列表的不同可以將同名函數(shù)進(jìn)行區(qū)分,就可保證名字在底層的全局唯一性。
那么c++中具體將名字修改成什么樣子了呢?
有如下代碼:
int Add(int left, int right);
double Add(double left, double right);
int main()
{
Add(1, 2);
Add(1.0, 2.0);
return 0;
}
//在vs下,對(duì)上述代碼進(jìn)行編譯鏈接,最后編譯器報(bào)錯(cuò):
//error LNK2019: 無法解析的外部符號(hào) "double cdecl Add(double,double)" (?Add@@YANNN@Z)
// error LNK2019: 無法解析的外部符號(hào) "int __cdecl Add(int,int)" (?Add@@YAHHH@Z)
通過上述錯(cuò)誤可以看出,編譯器實(shí)際在底層使用的不是Add名字,而是被重新修飾過的一個(gè)比較復(fù)雜的名字,被重新修飾后的名字中包含了:函數(shù)的名字以及參數(shù)類型。
visual stdio 下c++的修飾規(guī)則:
通過以上簽名及修飾后的名字可推得命名方式:
修飾后名字由“?”開頭,接著是函數(shù)名由“@"符號(hào)結(jié)尾的函數(shù)名:后面跟著由“@"結(jié)尾的類名“C”和名稱空間“N”,再一個(gè)“@”表示函數(shù)的名稱空間結(jié)束:第一個(gè)“A”表示函數(shù)調(diào)用類型為“_ cdecl” ,接著是函數(shù)的參數(shù)類型及返回值,由“@”結(jié)束,最后由“Z”結(jié)尾。其中A后面第一個(gè)是返回值類型,然后接下來到@之前都是形參的類型,H表示int,M表示float
那為什么c語言中,同名函數(shù)為什么不能構(gòu)成重載呢?
因?yàn)閏語言中的名字修飾只是在函數(shù)名前加了個(gè)下劃線,形參列表并未參與名字修飾,因而不能夠通過形參列表來區(qū)分各個(gè)同名函數(shù)。
在某個(gè)函數(shù)前加extern “C”,可將c++工程中某些函數(shù)按c的風(fēng)格來編譯
概念:給變量取了個(gè)別名,和變量共用一塊內(nèi)存空間,可以通過引用來改變變量。
定義:類型& 引用變量名=引用實(shí)體
注意:引用類型必須和引用實(shí)體的類型必須相同。
如:
int a = 10;
int& ra = a;//定義引用類型
printf("%p\n", &a);
printf("%p\n", &ra); //結(jié)果相同
引用特性:
1>引用在定義時(shí)必須初始化,不能存在空著的引用
int& ra ;//會(huì)發(fā)生錯(cuò)誤
//起了外號(hào),這個(gè)外號(hào)又不是任何人的,這個(gè)外號(hào)存在有什么意義?
2>一個(gè)變量可有多個(gè)引用(一個(gè)人可以起很多個(gè)別名)
3>引用一旦引用一個(gè)實(shí)體,再不能引用其他實(shí)體
int a=0;
int b=1;
int& ra=a;
ra=b; //ra不是改變了引用,只是將b的值賦給ra
printf("%d",a); //->1
常引用
const int a = 10;
int& ra = a; // 該語句編譯時(shí)會(huì)出錯(cuò),a為常量
//const修飾的變量,引用前也要加const,若不加,那么就可以通過引用修改變量的值了。
const int& ra = a;//正確寫法
int& b = 10; // 該語句編譯時(shí)會(huì)出錯(cuò),10為常量
//引用不能做常數(shù)的引用,要引用前面加const,常熟也是不能夠被修改的
const int& b = 10;
double d = 12.34;
int& rd = d; // 該語句編譯時(shí)會(huì)出錯(cuò),類型不同
const int& rd = d;//這個(gè)是正確的的,但rd并不是d的別名
//而是先通過a來形成一個(gè)臨時(shí)變量存放a的整數(shù)部分,然后ra引用這個(gè)臨時(shí)變量。但是該臨時(shí)變量不知道名字,也不知道地址,因而也修改不了,該臨時(shí)變量具有一定的常性,因而要在ra前加const
引用使用場(chǎng)景
1>做參數(shù):函數(shù)形參設(shè)為引用類型
void Swap(int& left, int& right)
{
int temp = left;
left = right;
right = temp;
}
說明:如果想要通過形參改變實(shí)參,可將形參設(shè)為普通類型 如果不想要通過形參改變實(shí)參,可將形參設(shè)為const類型。
效率:傳值的效率低于傳址、傳引用效率。傳地址和傳引用時(shí)間相同。因?yàn)閭饕煤蛡髦羔樀倪^程在內(nèi)存中的變化其實(shí)是一樣的,傳引用的過程在編譯時(shí),會(huì)轉(zhuǎn)成傳指針的形式,在編譯過程中,引用是按照指針方式來實(shí)現(xiàn)的
#include
struct A
{
int a[10000];
};
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(int*)-time:" << end1 - begin1 << endl;
cout << "TestFunc2(int&)-time:" << end2 - begin2 << endl;
}
// 運(yùn)行多次,檢測(cè)值和引用在傳參方面的效率區(qū)別
//結(jié)果都很小,而且相差無幾
//反匯編后,可看到傳引用的過程和傳指針的過程一模一樣。
int main()
{
for (int i = 0; i < 10; ++i)
{
TestRefAndValue();
}
return 0;
}
2>做返回值:將返回值類型設(shè)為引用類型
int& TestRefReturn(int& a)
{
a += 10;
return a;
}
注意:如果函數(shù)返回時(shí),離開函數(shù)作用域后,其棧上空間已經(jīng)還給系統(tǒng),因此不能用棧上的空間作為引用類型返回。因此,引用作為返回值,返回變量不應(yīng)受函數(shù)控制,即函數(shù)結(jié)束,變量的生命周期存在。比如:全局變量,static修飾的局部變量,用戶未釋放的堆,引用類型參數(shù)
發(fā)生該錯(cuò)誤有以下代碼:
int& Add(int a, int b)
{
int c = a + b;
return c;
}
//在函數(shù)調(diào)用完后,棧上的c占用的那一塊空間就被釋放了(可以覆蓋),因此就沒什么意義了
int main()
{
int& ret = Add(1, 2);
Add(3, 4);
cout << "Add(1, 2) is :"<< ret <7,Add(3, 4)將c的那一塊空間又覆蓋掉了
return 0;
}
通過比較,發(fā)現(xiàn)傳值和指針在作為傳參以及返回值類型上效率相差很大,因而可以讓引用作為返回值的地方就用引用,除非是要返回一個(gè)函數(shù)中定義的變量(該變量的空間會(huì)隨函數(shù)調(diào)用完而變得無效)要返回值外,其他情況都可用引用返回。
#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;
}
// 測(cè)試運(yùn)行10次,值和引用作為返回值效率方面的區(qū)別
int main()
{
for (int i = 0; i < 10; ++i)
TestReturnByRefOrValue();
return 0;
}
引用與指針
在語法概念上引用就是一個(gè)別名,沒有獨(dú)立空間,和其引用實(shí)體共用同一塊空間,但在底層實(shí)現(xiàn)上實(shí)際是有空間的,因?yàn)橐檬前凑罩羔樂绞絹韺?shí)現(xiàn)的。
int main()
{
int x = 10;
int& rx = x;
rx = 20;
int* px = &x;
*px = 20;
return 0;
}
對(duì)于該代碼我們來看反匯編代碼:
可發(fā)現(xiàn),在內(nèi)存中兩者在底層的使用方式是一樣的,引用也是按照指針方式來實(shí)現(xiàn)的
那兩者又有什么不同呢?
1> 引用在定義時(shí)必須初始化,指針沒有要求。因而指針需要判空,而引用不用,因?yàn)橐枚x時(shí)就初始化了
2> 引用在初始化時(shí)引用一個(gè)實(shí)體后,就不能再引用其他實(shí)體,而指針可以在任何時(shí)候指向任何一個(gè)同類型實(shí)體
3> 沒有NULL引用,但有NULL指針
4>在sizeof中含義不同:引用結(jié)果為引用類型的大小,但指針始終是地址空間所占字節(jié)個(gè)數(shù)(32位平臺(tái)下占4個(gè)字節(jié))
5>引用自加即引用的實(shí)體增加1,在連續(xù)的空間中指針自加即指針向后偏移一個(gè)類型的大小
6>有多級(jí)指針,但是沒有多級(jí)引用
7> 訪問實(shí)體方式不同,指針需要顯式解引用,引用編譯器自己處理
8> 引用比指針使用起來相對(duì)更安全。
概念:以inline修飾的函數(shù)叫做內(nèi)聯(lián)函數(shù),編譯時(shí)C++編譯器會(huì)在調(diào)用內(nèi)聯(lián)函數(shù)的地方展開,沒有函數(shù)壓棧的開銷,內(nèi)聯(lián)函數(shù)提升程序運(yùn)行的效率。
普通函數(shù)會(huì)進(jìn)行壓棧形成棧幀等操作
而內(nèi)聯(lián)函數(shù)在編譯時(shí)會(huì)直接將調(diào)用函數(shù)換為函數(shù)內(nèi)部的操作
查看方式:1. 在release模式下,查看編譯器生成的匯編代碼中是否存在call Add2. 在debug模式下,需要對(duì)編譯器進(jìn)行設(shè)置,否則不會(huì)展開(因?yàn)閐ebug模式下,編譯器默認(rèn)不會(huì)對(duì)代碼進(jìn)行優(yōu)化,給出vs2013的設(shè)置方式):功能->屬性->配置->c/c++->將常規(guī)中的調(diào)試信息格式改為程序數(shù)據(jù)庫,再將優(yōu)化中的內(nèi)聯(lián)函數(shù)擴(kuò)展改為只適用于_inline
特性
1> inline是一種以空間換時(shí)間的做法。所以代碼很長(zhǎng)或者有循環(huán)/遞歸的函數(shù)不適宜使用作為內(nèi)聯(lián)函數(shù)。
2>inline對(duì)于編譯器而言只是一個(gè)建議,編譯器會(huì)自動(dòng)優(yōu)化,如果定義為inline的函數(shù)體內(nèi)有循環(huán)/遞歸等等,編譯器優(yōu)化時(shí)會(huì)忽略掉內(nèi)聯(lián)。
3>inline不建議聲明和定義分離,分離會(huì)導(dǎo)致鏈接錯(cuò)誤。因?yàn)閕nline被展開,就沒有函數(shù)地址了,鏈接就會(huì)找不到。因而內(nèi)聯(lián)函數(shù)具有文件作用域,只在本文件有用,其他文件不可用。
// F.h
#include
using namespace std;
inline void f(int i);
// F.cpp
#include "F.h"
void f(int i)
{
cout << i << endl;
}
// main.cpp
#include "F.h"
int main()
{
f(10);
return 0;
}
// 鏈接錯(cuò)誤:main.obj : error LNK2019: 無法解析的外部符號(hào) "void __cdecl f(int)" (?
f@@YAXH@Z),該符號(hào)在函數(shù) _main 中被引用
內(nèi)聯(lián)函數(shù)與const、宏
在c++中,const修飾的變量有常量的特性也有宏的特性,在編譯時(shí)會(huì)發(fā)生替換和檢測(cè),即使通過指針修改也無法改變變量值。有如下代碼
const int a=1;
int *pa=(int *)a;
*pa=2;
printf("%d,%d",*pa,a);
//結(jié)果為2,1 a仍然沒有修改
而在c中是可以的,因?yàn)閏中是不會(huì)檢測(cè)的,通過指針也是修改const變量的
宏是在預(yù)處理時(shí)替換的,不參與編譯,也不可調(diào)試。
宏的優(yōu)點(diǎn):增強(qiáng)代碼的復(fù)用性。提高性能。
缺點(diǎn):
1>不方便調(diào)試宏。(因?yàn)轭A(yù)處理階段進(jìn)行了替換)
2>導(dǎo)致代碼可讀性差,可維護(hù)性差,容易誤用。
3>沒有類型安全的檢查 。
因此在c++中,可通過const來代替宏對(duì)常量的定義,用內(nèi)聯(lián)函數(shù)來代替宏對(duì)函數(shù)的定義
內(nèi)聯(lián)函數(shù)的優(yōu)缺點(diǎn):
https://mp.csdn.net/mdeditor/101083065#
概念:在C++中,auto作為一個(gè)新的類型指示符來定義變量,auto聲明的變量是由編譯器在編譯時(shí)期推導(dǎo)而得,變量被賦值什么類型,由初始化的值而定。
特性:
1>使用auto定義變量時(shí)必須對(duì)其進(jìn)行初始化,在編譯階段編譯器需要根據(jù)初始化表達(dá)式來推導(dǎo)auto的實(shí)際類型。
2>auto并非是一種“類型”的聲明,而是一個(gè)類型聲明時(shí)的“占位符”,編譯器在編譯期會(huì)將auto替換為變量實(shí)際的類型
int TestAuto()
{
return 10;
}
int main()
{
int a = 10;
auto b = a;
auto c = 'a';
auto d = TestAuto();
cout << typeid(b).name() << endl; //int
cout << typeid(c).name() << endl; //char
cout << typeid(d).name() << endl; //int
//auto e; 無法通過編譯,使用auto定義變量時(shí)必須對(duì)其進(jìn)行初始化
return 0;
}
使用方法
1>auto與指針和引用結(jié)合:用auto聲明指針類型時(shí),用auto和auto* 沒有任何區(qū)別,但用auto聲明引用類型時(shí)則必須加&.
int x = 1;
auto px = &x;
auto *ppx = &x;
auto& rx = x;
auto rrx = x;
cout << typeid(px).name() << endl;
cout << typeid(ppx).name() << endl;
cout << typeid(rx).name() << endl;
cout << typeid(rrx).name() << endl;
rx = 3;
cout << x << endl; //x發(fā)生了變化說明是引用
rrx = 2;
cout << x << endl; //x未發(fā)生變化,說明不是引用
2>auto在同一行定義多個(gè)變量,當(dāng)在同一行聲明多個(gè)變量時(shí),這些變量必須是相同的類型,否則編譯器將會(huì)報(bào)錯(cuò),因?yàn)榫幾g器實(shí)際只對(duì)第一個(gè)類型進(jìn)行推導(dǎo),然后用推導(dǎo)出來的類型定義其他變量。
auto f = 1, g = 2;
//auto h = 1, i = 2.3; //編譯會(huì)報(bào)錯(cuò),h和i類型不同
3>auto不能直接用來聲明數(shù)組
int h[] = { 1, 2, 3 };
//auto t[] = { 4,5,6 };//編譯時(shí)會(huì)發(fā)生錯(cuò)誤
為什么要引入這個(gè)概念?
對(duì)一個(gè)有范圍的集合由程序員來說明循環(huán)的范圍是多余的,有時(shí)候還會(huì)容易犯錯(cuò)誤。因此C++11中引入了基于范圍的for循環(huán)。
用法:for循環(huán)后的括號(hào)由冒號(hào)“ :”分為兩部分:第一部分是范圍內(nèi)用于迭代的變量,第二部分則表示被迭代的范圍。
int arr[] = { 1, 2, 3, 4, 5 };
for (auto& e : arr) //=>for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
e *= 2;
for (auto e : arr) //要對(duì)元素值進(jìn)行改變,變量前要加&,不改變,直接普通變量
cout << e << " ";
對(duì)于數(shù)組而言,就是數(shù)組中第一個(gè)元素和最后一個(gè)元素的范圍;對(duì)于類而言,應(yīng)該提供begin和end的方法,begin和end就是for循環(huán)迭代的范圍。
概念:nullptr指針空值常量,表示指針空值使用nullptr。
為什么要有nullptr,NULL為什么無法用于表示空指針了?
在指針定義時(shí),要初始化(否則會(huì)出現(xiàn)野指針),在c中用NULL來給一個(gè)沒有指向的指針,但其實(shí)NULL是一個(gè)宏,在傳統(tǒng)的C頭文件(stddef.h)中,可以看到如下代碼
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
可以看到,NULL可能被定義為字面常量0,或者被定義為無類型指針(void*)的常量,所以在傳空指針時(shí),會(huì)出現(xiàn)一些差強(qiáng)人意的錯(cuò)誤,如下:
void f(int)
{
cout<<"f(int)"<
因而用nullptr來代替C中NULL在指針中的用法。
并且nullptr也是有類型的,其類型為nullptr_t,僅僅可以被隱式轉(zhuǎn)化為指針類型,nullptr_t被定義在頭文件中:typedef decltype(nullptr) nullptr_t;
注意:
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。