青島做優(yōu)化網(wǎng)站哪家好公司網(wǎng)絡(luò)營銷推廣
目錄
C++概念
C++發(fā)展史
C++關(guān)鍵字(C++98)
命名空間
命名空間的定義
命名空間的使用
C++中的輸入&&輸出
缺省參數(shù)
缺省參數(shù)的概念
缺省參數(shù)的分類
函數(shù)重載
函數(shù)重載概念
函數(shù)重載實(shí)現(xiàn)
引用
引用的概念
引用的特性
常引用
引用的使用場景
引用做參數(shù)
引用做返回值
引用和指針的區(qū)別
內(nèi)聯(lián)函數(shù)
內(nèi)聯(lián)函數(shù)的概念
內(nèi)聯(lián)函數(shù)的特性
auto關(guān)鍵字
auto簡介
auto的使用細(xì)則
auto不能推導(dǎo)的場景?
基于范圍的for循環(huán)(C++11)
范圍for的語法
范圍for的使用條件
指針空值nullptr(C++11)
C++11中的指針空值
C++概念
????????C語言是結(jié)構(gòu)化和模塊化的語言,適合處理較小規(guī)模的程序。對(duì)于復(fù)雜的問題,規(guī)模較大的程序,需要高度的抽象和建模時(shí),C語言則不合適。為了解決軟件危機(jī),20世紀(jì)80年代,計(jì)算機(jī)界提出了OOP(object oriented programming:面向?qū)ο? 思想,支持面向?qū)ο蟮某绦蛟O(shè)計(jì)語言應(yīng)運(yùn)而生。
?1982年,Bjarne Stroustrup博士在C語言的基礎(chǔ)上引入并擴(kuò)充了面向?qū)ο蟮母拍?#xff0c;發(fā)明了一種新的程序語言。為了表達(dá)該語言與C語言的淵源關(guān)系,命名為C++。因此,C++是基于C語言而產(chǎn)生的,它既可以進(jìn)行C語言的過程化程序設(shè)計(jì),又可以進(jìn)行以抽象數(shù)據(jù)類型為特點(diǎn)的基于對(duì)象的程序設(shè)計(jì),還可以進(jìn)行面向?qū)ο蟮某绦蛟O(shè)計(jì)。
C++發(fā)展史
????????1979年,貝爾實(shí)驗(yàn)室的本賈尼等人試圖分析unix內(nèi)核的時(shí)候,試圖將內(nèi)核模塊化于是在C語言的基礎(chǔ)上進(jìn)行擴(kuò)展,增加了類的機(jī)制,完成了一個(gè)可以運(yùn)行的預(yù)處理程序,稱之為C with classes。
????????語言的發(fā)展也是隨著時(shí)代的進(jìn)步,在逐步遞進(jìn)的,讓我們來看看C++的歷史版本:
階段 | 內(nèi)容 |
C with classes | 類及派生類、公有和私有成員、類的構(gòu)造析構(gòu)、友元、內(nèi)聯(lián)函數(shù)、賦值運(yùn)算符重載等 |
C++1.0 | 添加虛函數(shù)概念,函數(shù)和運(yùn)算符重載,引用、常量等 |
C++2.0 | 更加完善支持面向?qū)ο?#xff0c;新增保護(hù)成員、多重繼承、對(duì)象的初始化、抽象類、靜態(tài)成員以及const成員函數(shù) |
C++3.0 | 進(jìn)一步完善,引入模板,解決多重繼承產(chǎn)生的二義性問題和相應(yīng)構(gòu)造和析構(gòu)的處理 |
C++98 | C++標(biāo)準(zhǔn)第一個(gè)版本,絕大多數(shù)編譯器都支持,得到了國際標(biāo)準(zhǔn)化組織(ISO)和美國標(biāo)準(zhǔn)化協(xié)會(huì)認(rèn)可,以模板方式重寫C++標(biāo)準(zhǔn)庫,引入了STL(標(biāo)準(zhǔn)模板庫) |
C++03 | C++標(biāo)準(zhǔn)第二個(gè)版本,語言特性無大改變,主要∶修訂錯(cuò)誤、減少多異性 |
C++05 | C++標(biāo)準(zhǔn)委員會(huì)發(fā)布了一份計(jì)數(shù)報(bào)告(Technical Report,TR1),正式更名C++0x,即∶計(jì)劃在本世紀(jì)第一個(gè)10年的某個(gè)時(shí)間發(fā)布 |
C++11 | 增加了許多特性,使得C++更像一種新語言,比如∶正則表達(dá)式、基于范圍for循環(huán)、auto關(guān)鍵字、新容器、列表初始化、標(biāo)準(zhǔn)線程庫等 |
C++14 | 對(duì)C++11的擴(kuò)展,主要是修復(fù)C++11中漏洞以及改進(jìn),比如∶泛型的lambda表達(dá)式,auto的返回值類型推導(dǎo),二進(jìn)制字面常量等 |
C++17 | 在C++11上做了一些小幅改進(jìn),增加了19個(gè)新特性,比如∶static_assert()的文本信息可選,Fold表達(dá)式用于可變的模板,if和switch語句中的初始化器等 |
C++還在不斷地向后發(fā)展...
C++關(guān)鍵字(C++98)
????????C++中總共63個(gè)關(guān)鍵字,包括了C語言中32個(gè)關(guān)鍵字。
命名空間
????????在C/C++中,變量、函數(shù)和后面要學(xué)到的類都是大量存在的,這些變量、函數(shù)和類的名稱將都存在于全局作用域中,可能會(huì)導(dǎo)致很多沖突。使用命名空間的目的是對(duì)標(biāo)識(shí)符的名稱進(jìn)行本地化,以避免命名沖突或名字污染,namespace關(guān)鍵字的出現(xiàn)就是針對(duì)這種問題的。
命名空間的定義
????????定義命名空間,需要使用到namespace關(guān)鍵字,后面跟命名空間的名字,然后接一對(duì){}即可,{}中即為命名空間的成員。
//命名空間的普通定義
namespace N1 //N1為命名空間的名稱
{//在命名空間中,既可以定義變量,也可以定義函數(shù)int a;int Add(int x, int y){return x + y;}
}
//命名空間的嵌套定義
namespace N1 //定義一個(gè)名為N1的命名空間
{int a;int b;namespace N2 //嵌套定義另一個(gè)名為N2的命名空間{int c;int d;}
}
命名空間的使用
????????C++為了防止命名沖突,把自己庫里面的東西都定義在一個(gè)std的命名空間中要使用標(biāo)準(zhǔn)庫里面的東西,有三種方式
? ? ? ? 1、指定命名空間–麻煩,每個(gè)地方都要指定,但也是最規(guī)范的方式。
int c = 100;
namespace N
{int a = 10;int b = 20;int Add(int left, int right){return left + right;}int Sub(int left, int right){return left - right;}
}
????????2、把std整個(gè)展開,相當(dāng)于庫里面的東西全部到全局域里面去了,使用起來方便但是可能會(huì)有與自己命名空間定義的沖突,規(guī)范工程中不推薦這種,日常練習(xí)可以用這種。
using namespace std;
????????3、對(duì)部分常用的庫里面的東西展開->針對(duì)1和2的折中方案,項(xiàng)目中也經(jīng)常使用
using std::cout;
using std::endl;
int main()
{printf("%d\n", N::a);printf("%d\n", N::b);printf("%d\n", N::Add(1, 2));printf("%d\n", N::Sub(1, 2));int c = 10;printf("%d\n", c); //局部變量優(yōu)先,所以c為10printf("%d\n", ::c); //指定訪問左邊域,空白表示全局域
}
C++中的輸入&&輸出
????????1、使用cout標(biāo)準(zhǔn)輸出(控制臺(tái))和cin標(biāo)準(zhǔn)輸入(鍵盤)時(shí),必須包含< iostream >頭文件以及std標(biāo)準(zhǔn)命名空間。
????????注意:早期標(biāo)準(zhǔn)庫將所有功能在全局域中實(shí)現(xiàn),聲明在.h后綴的頭文件中,使用時(shí)只需包含對(duì)應(yīng)頭文件即可,后來將其實(shí)現(xiàn)在std命名空間下,為了和C頭文件區(qū)分,也為了正確使用命名空間,規(guī)定C++頭文件不帶.h;舊編譯器(vc 6.0)中還支持<iostream.h>格式,后續(xù)編譯器已不支持,因此推薦使用+std的方式。
????????2、使用C++輸入輸出更方便,不需增加數(shù)據(jù)格式控制,比如:整形–%d,字符–%c。
????????3、ostream 類型全局對(duì)象,istream 類型全局對(duì)象 ,endl全局的換行符號(hào)。
struct Person
{char name[10];int age;
};
int main()
{std::cout << "bit education ";std::cout << "bit education" << std::endl;//cout與cin對(duì)比C語言printf\scanf 來說可以自動(dòng)識(shí)別類型(函數(shù)重載+運(yùn)算符重載)int a = 10;int* p = &a;printf("%d,%p\n", a, p);std::cout << a << "," << p << std::endl;std::cin >> a;printf("%d\n", a);char str[100];std::cin >> str; //cin不用&,因?yàn)橐胹td::cout << str << std::endl;struct Person P = { "uzi", 23 }; //格式化輸出printf比cout好printf("name:%s age:%d\n", P.name, P.age);std::cout << "name:" << P.name<<" age:"<< P.age << "\n";
}
缺省參數(shù)
缺省參數(shù)的概念
????????缺省參數(shù)是聲明或定義函數(shù)時(shí)為函數(shù)的參數(shù)指定一個(gè)默認(rèn)值。在調(diào)用該函數(shù)時(shí),如果沒有指定實(shí)參則采用該默認(rèn)值,否則使用指定的實(shí)參。
#include <iostream>
using namespace std;
void Print(int a = 0)
{cout << a << endl;
}
int main()
{Print();//沒有指定實(shí)參,使用參數(shù)的默認(rèn)值(打印0)Print(10);//指定了實(shí)參,使用指定的實(shí)參(打印10)return 0;
}
缺省參數(shù)的分類
- 半缺省參數(shù)
void testFunc3(int a, int b = 10, int c = 20) {cout << "a = " << a << endl;cout << "b = " << b << endl;cout << "c = " << c << endl; }
- 全缺省參數(shù)
void testFunc2(int a = 10, int b = 20, int c = 30) {cout << "a = " << a << endl;cout << "b = " << b << endl;cout << "c = " << c << endl; }
- 正常參數(shù)
void testFunc1(int a = 0) {std::cout << a << std::endl; }int main() {testFunc1(10);testFunc2();testFunc3(1);return 0; }
注意:
- 半缺省參數(shù)必須從右往左依次來給出,不能間隔著給
- 缺省參數(shù)不能在函數(shù)聲明和定義中同時(shí)出現(xiàn)
- 缺省值必須是常量或者全局變量
- C語言不支持(編譯器不支持)
函數(shù)重載
函數(shù)重載概念
????????是函數(shù)的一種特殊情況,C++允許在同一作用域中聲明幾個(gè)功能類似的同名函數(shù),這些同名函數(shù)的形參列表(參數(shù)個(gè)數(shù) 或 類型 或 順序)必須不同,常用來處理實(shí)現(xiàn)功能類似數(shù)據(jù)類型不同的問題。
函數(shù)重載實(shí)現(xiàn)
int Add(int left, int right)
{return left + right;
}
double Add(double left, double right)
{return left + right;
}
int main()
{cout << Add(10, 20) << endl;cout << Add(10.5, 20.0) << endl;//fun();return 0;
}
注意(特別重要):?缺省參數(shù)缺省參數(shù)符合重載的定義,但如果調(diào)用的時(shí)候編譯器不識(shí)別函數(shù)重載調(diào)用哪個(gè)函數(shù),所以分情況討論。
void fun(int a, int b, int c = 10)
{}
void fun(int a, int b)
{}
?
函數(shù)命名規(guī)則–>C++支持重載,C不支持
????????為什么C++支持函數(shù)重載,而C語言不支持函數(shù)重載呢?
????????一個(gè)程序要運(yùn)行起來,需要經(jīng)歷以下幾個(gè)階段:預(yù)處理、編譯、匯編、鏈接。
在C++中:
函數(shù)名 Mangling(名稱修飾):C++編譯器使用函數(shù)名和參數(shù)類型來生成一個(gè)唯一的函數(shù)標(biāo)識(shí)符(這個(gè)過程稱為名稱修飾或編譯器編碼)。即便兩個(gè)函數(shù)名字相同,只要它們的參數(shù)類型、個(gè)數(shù)或者順序不同,編譯器就會(huì)生成不同的內(nèi)部表示(即不同的函數(shù)名),這樣就可以在鏈接階段區(qū)分它們,實(shí)現(xiàn)函數(shù)重載。
更強(qiáng)大的類型系統(tǒng):C++作為一個(gè)面向?qū)ο蟮恼Z言,擁有更復(fù)雜的類型系統(tǒng),支持多態(tài)等特性,函數(shù)重載是其支持多態(tài)性的一個(gè)重要方面。
而在C語言中:
簡單的函數(shù)命名規(guī)則:C語言的編譯器在編譯時(shí),函數(shù)名不包含參數(shù)類型信息。對(duì)于C編譯器來說,函數(shù)名必須是唯一的,如果有兩個(gè)函數(shù)名字相同,無論參數(shù)列表是否一致,都會(huì)導(dǎo)致編譯錯(cuò)誤,因?yàn)榫幾g器無法根據(jù)參數(shù)列表來區(qū)分它們。
設(shè)計(jì)哲學(xué):C語言的設(shè)計(jì)哲學(xué)傾向于簡潔和直接,它沒有引入函數(shù)重載這樣的特性以保持語言的簡單性和緊湊性。
引用
引用的概念
????????引用不是新定義一個(gè)變量,而是給已存在變量取了一個(gè)別名,編譯器不會(huì)為引用變量開辟內(nèi)存空間,它和它引用的變量共用同一塊內(nèi)存空間。
????????其使用的基本形式為:類型& 引用變量名(對(duì)象名) = 引用實(shí)體。
int main()
{int a = 10;int& b = a;//給變量a去了一個(gè)別名,叫bcout << "a = " << a << endl;//a打印結(jié)果為10cout << "b = " << b << endl;//b打印結(jié)果也是10b = 20;//改變b也就是改變了acout << "a = " << a << endl;//a打印結(jié)果為20cout << "b = " << b << endl;//b打印結(jié)果也是為20return 0;
}
注:引用類型必須和引用實(shí)體是同種類型。?
引用的特性
1、引用在定義時(shí)必須初始化
正確示例:int a = 10;
int& b = a;//引用在定義時(shí)必須初始化
錯(cuò)誤示例:int c = 10;
int &d;//定義時(shí)未初始化
d = c;
2、 一個(gè)變量可以有多個(gè)引用
int a = 10;
int& b = a;
int& c = a;
int& d = a;
此時(shí),b、c、d都是變量a的引用。?
3、引用一旦引用了一個(gè)實(shí)體,就不能再引用其他實(shí)體
int a = 10;
int& b = a;
此時(shí),b已經(jīng)是a的引用了,b不能再引用其他實(shí)體。如果你寫下以下代碼,想讓b轉(zhuǎn)而引用另一個(gè)變量c:
int a = 10;
int& b = a;
int c = 20;
b = c;//你的想法:讓b轉(zhuǎn)而引用c
?但該代碼并沒有隨你的意,該代碼的意思是:將b引用的實(shí)體賦值為c,也就是將變量a的內(nèi)容改成了20。
常引用
????????上面提到,引用類型必須和引用實(shí)體是同種類型的。但是僅僅是同種類型,還不能保證能夠引用成功,我們?nèi)粲靡粋€(gè)普通引用類型去引用其對(duì)應(yīng)的類型,但該類型被const所修飾,那么引用將不會(huì)成功。
int main()
{const int a = 10;//int& ra = a; //該語句編譯時(shí)會(huì)出錯(cuò),a為常量const int& ra = a;//正確//int& b = 10; //該語句編譯時(shí)會(huì)出錯(cuò),10為常量const int& b = 10;//正確return 0;
}
????????我們可以將被const修飾了的類型理解為安全的類型,因?yàn)槠洳荒鼙恍薷?。我們?nèi)魧⒁粋€(gè)安全的類型交給一個(gè)不安全的類型(可被修改),那么將不會(huì)成功。?
引用的使用場景
引用做參數(shù)
????????還記得C語言中的交換函數(shù),學(xué)習(xí)C語言的時(shí)候經(jīng)常用交換函數(shù)來說明傳值和傳址的區(qū)別?,F(xiàn)在我們學(xué)習(xí)了引用,可以不用指針作為形參了:
//交換函數(shù)
void Swap(int& a, int& b)
{int tmp = a;a = b;b = tmp;
}
????????因?yàn)樵谶@里a和b是傳入實(shí)參的引用,我們將a和b的值交換,就相當(dāng)于將傳入的兩個(gè)實(shí)參交換了。?
引用做返回值
????????當(dāng)然引用也能做返回值,但是要特別注意,我們返回的數(shù)據(jù)不能是函數(shù)內(nèi)部創(chuàng)建的普通局部變量,因?yàn)樵诤瘮?shù)內(nèi)部定義的普通的局部變量會(huì)隨著函數(shù)調(diào)用的結(jié)束而被銷毀。我們返回的數(shù)據(jù)必須是被static修飾或者是動(dòng)態(tài)開辟的或者是全局變量等不會(huì)隨著函數(shù)調(diào)用的結(jié)束而被銷毀的數(shù)據(jù)。
int& Add(int a, int b)
{static int c = a + b;return c;
}
注意:如果函數(shù)返回時(shí),出了函數(shù)作用域,返回對(duì)象還未還給系統(tǒng),則可以使用引用返回;如果已經(jīng)還給系統(tǒng)了,則必須使用傳值返回。
引用和指針的區(qū)別
引用和指針在C++中都是用來存儲(chǔ)其他變量的地址,但它們之間存在幾個(gè)關(guān)鍵的區(qū)別:
別名與獨(dú)立實(shí)體:
????????引用:是一個(gè)已存在變量的別名,也就是說,一旦引用被初始化為某個(gè)變量,它就是那個(gè)變量的另一個(gè)名字,對(duì)引用的操作實(shí)際上就是對(duì)原始變量的操作。
????????指針:是一個(gè)獨(dú)立的實(shí)體,它存儲(chǔ)了一個(gè)內(nèi)存地址的值,該地址指向另一個(gè)變量。使用指針時(shí),你需要通過解引用操作(*)來訪問目標(biāo)變量的內(nèi)容。
初始化:
????????引用:必須在聲明時(shí)被初始化,并且一旦初始化后,就不能改變引用的對(duì)象。它必須被初始化為一個(gè)已存在的對(duì)象。
????????指針:可以在聲明時(shí)初始化,也可以稍后初始化。它可以被初始化為
nullptr
,或者任何合法對(duì)象的地址,并且在生命周期內(nèi)可以改變指向其他對(duì)象。空值:
????????引用:不允許為
NULL
或未定義,總是必須關(guān)聯(lián)到合法的存儲(chǔ)位置。????????指針:可以指向
NULL
,這使得指針可以用來表示“沒有對(duì)象”。sizeof操作:
????????引用:
sizeof
引用得到的是被引用對(duì)象的大小,因?yàn)樗皇莿e名。????????指針:
sizeof
指針得到的是指針本身的大小,不論它指向什么類型的對(duì)象。可變性:
????????引用:一旦引用被初始化,它就不能重新綁定到另一個(gè)對(duì)象。
????????指針:可以改變指針的值,讓它指向不同的對(duì)象。
操作符行為:
????????對(duì)于**++或--**運(yùn)算符,如果應(yīng)用于指針,它們會(huì)改變指針自身的值(使其指向下一個(gè)或前一個(gè)內(nèi)存位置);如果應(yīng)用于引用,則是對(duì)引用所指對(duì)象的值進(jìn)行增減操作。
使用場景:
????????引用通常用于函數(shù)參數(shù)傳遞、返回值以及提供更安全和方便的訪問方式。
指針提供了更多的靈活性,特別是在動(dòng)態(tài)內(nèi)存管理、數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)和低級(jí)別編程中。?
內(nèi)聯(lián)函數(shù)
內(nèi)聯(lián)函數(shù)的概念
????????以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)行效率。
????????我們可以通過觀察調(diào)用普通函數(shù)和內(nèi)聯(lián)函數(shù)的匯編代碼來進(jìn)一步查看其優(yōu)勢:
int Add(int a, int b)
{return a + b;
}
int main()
{int ret = Add(1, 2);return 0;
}
下圖左是以上代碼的匯編代碼,下圖右是函數(shù)Add加上inline后的匯編代碼:?
內(nèi)聯(lián)函數(shù)的特性
????????1、inline是一種以空間換時(shí)間的做法,省了去調(diào)用函數(shù)的額外開銷。由于內(nèi)聯(lián)函數(shù)會(huì)在調(diào)用的位置展開,所以代碼很長或者有遞歸的函數(shù)不適宜作為內(nèi)聯(lián)函數(shù)。頻繁調(diào)用的小函數(shù)建議定義成內(nèi)聯(lián)函數(shù)。
????????2、inline對(duì)于編譯器而言只是一個(gè)建議,編譯器會(huì)自動(dòng)優(yōu)化,如果定義為inline的函數(shù)體內(nèi)有遞歸等,編譯器優(yōu)化時(shí)會(huì)忽略掉內(nèi)聯(lián)。
????????3、inline不建議聲明和定義分離,分離會(huì)導(dǎo)致鏈接錯(cuò)誤。因?yàn)閕nline被展開,就沒有函數(shù)地址了鏈接就會(huì)找不到。
auto關(guān)鍵字
auto簡介
????????在早期的C/C++中auto的含義是:使用auto修飾的變量是具有自動(dòng)存儲(chǔ)器的局部變量,但遺憾的是一直沒有人去使用它。
????????在C++11中,標(biāo)準(zhǔn)委員會(huì)賦予了auto全新的含義:auto不再是一個(gè)存儲(chǔ)類型指示符,而是作為一個(gè)新的類型指示符來指示編譯器,auto聲明的變量必須由編譯器在編譯時(shí)期推導(dǎo)而得。
#include <iostream>
using namespace std;
double Fun()
{return 3.14;
}
int main()
{int a = 10;auto b = a;auto c = 'A';auto d = Fun();//打印變量b,c,d的類型cout << typeid(b).name() << endl;//打印結(jié)果為intcout << typeid(c).name() << endl;//打印結(jié)果為charcout << typeid(d).name() << endl;//打印結(jié)果為doublereturn 0;
}
注意:使用auto變量時(shí)必須對(duì)其進(jìn)行初始化,在編譯階段編譯器需要根據(jù)初始化表達(dá)式來推導(dǎo)auto的實(shí)際類型。因此,auto并非是一種“類型”的聲明,而是一個(gè)類型聲明的“占位符”,編譯器在編譯期會(huì)將auto替換為變量實(shí)際的類型。
auto的使用細(xì)則
1、auto與指針和引用結(jié)合起來使用
用auto聲明指針類型時(shí),用auto和auto*沒有任何區(qū)別,但用auto聲明引用類型時(shí)必須加&。
#include <iostream>
using namespace std;
int main()
{int a = 10;auto b = &a; //自動(dòng)推導(dǎo)出b的類型為int*auto* c = &a; //自動(dòng)推導(dǎo)出c的類型為int*auto& d = a; //自動(dòng)推導(dǎo)出d的類型為int//打印變量b,c,d的類型cout << typeid(b).name() << endl;//打印結(jié)果為int*cout << typeid(c).name() << endl;//打印結(jié)果為int*cout << typeid(d).name() << endl;//打印結(jié)果為intreturn 0;
}
注意:用auto聲明引用時(shí)必須加&,否則創(chuàng)建的只是與實(shí)體類型相同的普通變量。
2、在同一行定義多個(gè)變量
????????當(dāng)在同一行聲明多個(gè)變量時(shí),這些變量必須是相同的類型,否則編譯器將會(huì)報(bào)錯(cuò),因?yàn)榫幾g器實(shí)際只對(duì)第一個(gè)類型進(jìn)行推導(dǎo),然后用推導(dǎo)出來的類型定義其他變量。?
int main()
{auto a = 1, b = 2; //正確auto c = 3, d = 4.0; //編譯器報(bào)錯(cuò):“auto”必須始終推導(dǎo)為同一類型return 0;
}
auto不能推導(dǎo)的場景?
1、auto不能作為函數(shù)的參數(shù)
?以下代碼編譯失敗,auto不能作為形參類型,因?yàn)榫幾g器無法對(duì)x的實(shí)際類型進(jìn)行推導(dǎo)。
void TestAuto(auto x)
{ }
?2、auto不能直接用來聲明數(shù)組
int main()
{int a[] = { 1, 2, 3 };auto b[] = { 4, 5, 6 };//errorreturn 0;
}
基于范圍的for循環(huán)(C++11)
范圍for的語法
????????若是在C++98中我們要遍歷一個(gè)數(shù)組,可以按照以下方式:
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//將數(shù)組元素值全部乘以2
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{arr[i] *= 2;
}
//打印數(shù)組中的所有元素
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{cout << arr[i] << " ";
}
cout << endl;
????????以上方式也是我們C語言中所用的遍歷數(shù)組的方式,但對(duì)于一個(gè)有范圍的集合而言,循環(huán)是多余的,有時(shí)還容易犯錯(cuò)。因此C++11中引入了基于范圍的for循環(huán)。for循環(huán)后的括號(hào)由冒號(hào)分為兩部分:第一部分是范圍內(nèi)用于迭代的變量,第二部分則表示被迭代的范圍。?
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//將數(shù)組元素值全部乘以2
for (auto& e : arr)
{e *= 2;
}
//打印數(shù)組中的所有元素
for (auto e : arr)
{cout << e << " ";
}
cout << endl;
注意:與普通循環(huán)類似,可用continue來結(jié)束本次循環(huán),也可以用break來跳出整個(gè)循環(huán)。
范圍for的使用條件
1、for循環(huán)迭代的范圍必須是確定的
?對(duì)于數(shù)組而言,就是數(shù)組中第一個(gè)元素和最后一個(gè)元素的范圍;對(duì)于類而言,應(yīng)該提供begin和end的方法,begin和end就是for循環(huán)迭代的范圍。
2、迭代的對(duì)象要實(shí)現(xiàn)++和==操作
?這是關(guān)于迭代器的問題,大家先了解一下。
指針空值nullptr(C++11)
????????在良好的C/C++編程習(xí)慣中,在聲明一個(gè)變量的同時(shí)最好給該變量一個(gè)合適的初始值,否則可能會(huì)出現(xiàn)不可預(yù)料的錯(cuò)誤。比如未初始化的指針,如果一個(gè)指針沒有合法的指向,我們基本都是按如下方式對(duì)其進(jìn)行初始化:
int* p1 = NULL;
int* p2 = 0;
????????NULL其實(shí)是一個(gè)宏,在傳統(tǒng)的C頭文件(stddef.h)中可以看到如下代碼:
/* Define NULL pointer value */
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else /* __cplusplus */
#define NULL ((void *)0)
#endif /* __cplusplus */
#endif /* NULL */
?????????可以看到,NULL可能被定義為字面常量0,也可能被定義為無類型指針(void*)的常量。但是不論采取何種定義,在使用空值的指針時(shí),都不可避免的會(huì)遇到一些麻煩,例如:
#include <iostream>
using namespace std;
void Fun(int p)
{cout << "Fun(int)" << endl;
}
void Fun(int* p)
{cout << "Fun(int*)" << endl;
}
int main()
{Fun(0); //打印結(jié)果為 Fun(int)Fun(NULL); //打印結(jié)果為 Fun(int)Fun((int*)NULL); //打印結(jié)果為 Fun(int*)return 0;
}
????????程序本意本意是想通過Fun(NULL)調(diào)用指針版本的Fun(int* p)函數(shù),但是由于NULL被定義為0,Fun(NULL)最終調(diào)用的是Fun(int p)函數(shù)。
注:在C++98中字面常量0,既可以是一個(gè)整型數(shù)字,也可以是無類型的指針(void*)常量,但編譯器默認(rèn)情況下將其看成是一個(gè)整型常量,如果要將其按照指針方式來使用,必須對(duì)其進(jìn)行強(qiáng)制轉(zhuǎn)換。
C++11中的指針空值
????????對(duì)于C++98中的問題,C++11引入了關(guān)鍵字nullptr。
注意:
?1、在使用nullptr表示指針空值時(shí),不需要包含頭文件,因?yàn)閚ullptr是C++11作為關(guān)鍵字引入的。
?2、在C++11中,sizeof(nullptr)與sizeof((void*)0)所占的字節(jié)數(shù)相同。
?3、為了提高代碼的健壯性,在后序表示指針空值時(shí)建議最好使用nullptr。