🥁作者:華丞臧
成都創(chuàng)新互聯(lián)公司主營八宿網(wǎng)站建設的網(wǎng)絡公司,主營網(wǎng)站建設方案,重慶APP開發(fā)公司,八宿h5微信小程序定制開發(fā)搭建,八宿網(wǎng)站營銷推廣歡迎八宿等地區(qū)企業(yè)咨詢
📕????專欄:【C++】
各位讀者老爺如果覺得博主寫的不錯,請諸位多多支持(點贊+收藏+關注)。如果有錯誤的地方,歡迎在評論區(qū)指出。推薦一款刷題網(wǎng)站 👉LeetCode
目錄
一、C++關鍵字(C++98)
二、命名空間?
2.1 命名空間定義
2.2 命名空間使用
三、C++輸入&輸出
四、缺省參數(shù)
4.1 缺省參數(shù)概念
4.2 缺省參數(shù)分類
全缺省參數(shù)
半缺省參數(shù)
五、函數(shù)重載
5.1 函數(shù)重載概念
5.2 C++支持函數(shù)重載的原理--名字修飾(name mangling)
六、內(nèi)聯(lián)函數(shù)
6.1 內(nèi)聯(lián)函數(shù)概念
6.2 特性
七、auto關鍵字(C++11)
7.1 類型別名思考
7.2 auto
7.3 auto使用細則
1. auto與指針和引用結合起來使用
2. 在同一行定義多個變量
7.4 auto不能推導的場景
八、基于范圍的for循環(huán)(C++11)
8.1 范圍for的語法
8.2 范圍for的使用條件
九、指針空值nullptr(C++)
9.1 C++98中的指針空值
C++總計63個關鍵字,對比C語言32個關鍵字。
二、命名空間?在C/C++中,變量、函數(shù)和后面要學到的類都是大量存在的,這些變量、函數(shù)和類的名稱將都存在于全局作用域中,可能會導致很多沖突。使用命名空間的目的是對標識符的名稱進行本地化,以避免命名沖突或名字污染,namespace關鍵字的出現(xiàn)就是針對這種問題。
在C語言當中,不能有相同名字的變量或者函數(shù)名。
#include#includeint rand = 10;
// C語言沒辦法解決類似這樣的命名沖突問題,所以C++提出了namespace來解決
int main()
{
printf("%d\n", rand);
return 0;
}
// 編譯后后報錯:error C2365: “rand”: 重定義;以前的定義是“函數(shù)”
2.1 命名空間定義定義命名空間,需要使用到?namespace?關鍵字,后面跟命名空間的名字,然后接一對{}即可,{}中即為命名空間的成員。
// bit是命名空間的名字,一般開發(fā)中是用項目名字做命名空間名。
// 我們上課用的是bit,大家下去以后自己練習用自己名字縮寫即可,如張三:zs
// 1. 正常的命名空間定義
namespace bit
{
// 命名空間中可以定義變量/函數(shù)/類型
int rand = 10;
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
}
//2. 命名空間可以嵌套
// test.cpp
namespace N1
{
int a;
int b;
int Add(int left, int right)
{
return left + right;
}
namespace N2
{
int c;
int d;
int Sub(int left, int right)
{
return left - right;
}
};
}
//3. 同一個工程中允許存在多個相同名稱的命名空間,編譯器最后會合成同一個命名空間中。
// ps:一個工程中的test.h和上面test.cpp中兩個N1會被合并成一個
// test.h
namespace N1
{
int Mul(int left, int right)
{
return left * right;
}
}
注意:一個命名空間就定義了一個新的作用域,命名空間中的所有內(nèi)容都局限于該命名空間中
2.2 命名空間使用命名空間中成員該如何使用呢?
#includenamespace bit
{
//命名空間中可以定義變量/函數(shù)/類型
int a = 0;
int b = 1;
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
}
int main()
{
//編譯報錯:error C2065: “a”: 未聲明的標識符
printf("%d\n", a);
//正確使用
printf("%d\n",bit::a);
return 0;
}
命名空間的使用有三種方式:
int main()
{
printf("%d\n", N::a);
return 0;
}
using N::b;
int main()
{
printf("%d\n", N::a);
printf("%d\n", b);
return 0;
}
using namespce N;
int main()
{
printf("%d\n", N::a);
printf("%d\n", b);
Add(10, 20);
return 0;
}
三、C++輸入&輸出命名空間中的變量是全局變量,命名空間不會影響變量的生命周期;只是限定變量的作用域,影響編譯查找規(guī)則;命名空間定義是在全局,所以放在靜態(tài)區(qū)。
第一個C++程序
#includeusing namespace std;
int main()
{
cout<< "Hello world!"<< endl;
return 0;
}
四、缺省參數(shù) 4.1 缺省參數(shù)概念說明:
- 使用cout標準輸出對象(控制臺)和cin標準輸入對象(鍵盤)時,必須包含
頭文件,以及按命名空間使用方法使用std. - cout和cin是全局的流對象,endl是特殊的C++符號,表示換行輸出等同于‘\0’,他們都包含在
頭文件中。 - <<是流插入運算符,>>是流提取運算符。
- 使用這種C++輸入輸出方式更加方便,相較于C語言C++不需要手動控制格式,C++的輸入輸出可以自動識別變量類型。
- 實際上cout和cin分別是ostream和istream類型的對象,<<和>>也涉及運算符重載等知識。
4.2 缺省參數(shù)分類缺省參數(shù)是聲明或定義函數(shù)時為函數(shù)的參數(shù)指定一個缺省值。在調(diào)用這個函數(shù)時,如果用戶沒有指定實參則采用該形參的缺省值,否則使用指定實參。
所謂全缺省參數(shù)就是指一個函數(shù)的全部參數(shù)都指定一個缺省值。
void Func(int a = 10, int b = 20, int c = 30)
{
cout<<"a = "<
所謂半缺省參數(shù)就是指函數(shù)參數(shù)中至少有一個非缺省參數(shù)。?
//錯誤
void Func(int a = 10, int b = 20, int c)
{
cout<<"a = "<
五、函數(shù)重載 5.1 函數(shù)重載概念注意:
- 半缺省參數(shù)必須從右往左依次給出,不能間隔著給;
- 缺省參數(shù)不能在函數(shù)聲明和定義中同時出現(xiàn);
- 缺省值必須是常量或者全局變量;
- 缺省參數(shù)不能在函數(shù)聲明和定義中同時出現(xiàn);當同時有聲明和定義時,缺省參數(shù)只能在.h當中。
- C語言不支持缺省參數(shù)(編譯器不支持)。
函數(shù)重載是函數(shù)的一種特殊情況,C++允許在同一作用域中聲明幾個功能類似的同名函數(shù),這些同名函數(shù)的形參列表(參數(shù)個數(shù)或類型或類型順序)不同,常用來處理實現(xiàn)功能類似數(shù)據(jù)類型不同的問題。
#includeusing namespace std;
// 1、參數(shù)類型不同
int Add(int left, int right)
{
cout<< left + right<< endl;
return left + right;
}
double Add(double left, double right)
{
cout<< left + right<< endl;
return left + right;
}
// 2、參數(shù)個數(shù)不同
void f()
{
cout<< "f()"<< endl;
}
void f(int a)
{
cout<< "f(int a)"<< endl;
}
// 3、參數(shù)類型順序不同
void f(int a, char b)
{
cout<< "f(int a,char b)"<< endl;
}
void f(char b, int a)
{
cout<< "f(char b, int a)"<< endl;
}
int main()
{
Add(1, 2);
Add(1.1, 2.2);
f();
f(10);
f(10, 'a');
f('a', 10);
return 0;
}
5.2 C++支持函數(shù)重載的原理--名字修飾(name mangling)為什么C++支持函數(shù)重載而C語言不支持函數(shù)重載呢?
六、內(nèi)聯(lián)函數(shù) 6.1 內(nèi)聯(lián)函數(shù)概念????????在C/C++中,一個程序要運行起來,需要經(jīng)歷以下幾個階段:預處理、編譯、匯編、鏈接。在編譯階段,編譯器會匯總全局的符號,如main函數(shù)、全局變量、函數(shù)名等;然后在匯編階段,編譯器會給編譯時匯總的每個符號分配一個地址(注意如果符號只是聲明則會分配一個無效的地址),并且在對應的.o文件中形成一個符號表;各個.o文件的符號表在鏈接時會合并,并且在合并時同名的符號會選擇有效的地址進行合并。
? 在C語言當中,C語言的編譯器并不會根據(jù)函數(shù)參數(shù)的特性對函數(shù)名進行修飾;這就導致即使函數(shù)形參列表不同只要函數(shù)名相同,那么符號匯總時就會出現(xiàn)同名的符號,這時編譯器就會報錯。
? 在C++中,同名的函數(shù)只要形參列表不同,C++編譯器會根據(jù)名字修飾規(guī)則對函數(shù)名進行修飾,這時在編譯時同名但形參列表不同的函數(shù)就會形成不同的符號;既然不出現(xiàn)同名符號,編譯器自然不會報相應的錯誤。
? 如果兩個函數(shù)函數(shù)名和參數(shù)是一樣的,返回值不同是不構成重載的,因為調(diào)用是存在二義性,編譯器無法區(qū)分。
注意:不同平臺的C++編譯器的名字修飾規(guī)則不一樣,但是產(chǎn)生的效果是一樣的。
以inline修飾的函數(shù)叫做內(nèi)聯(lián)函數(shù),編譯時C++編譯器會在調(diào)用內(nèi)聯(lián)函數(shù)的地方展開,沒有函數(shù)調(diào)用建立棧幀的開銷,內(nèi)聯(lián)函數(shù)提升程序運行的效率。
如果在上述函數(shù)前增加?inline?關鍵字將其改成內(nèi)聯(lián)函數(shù),在編譯期間編譯器會用函數(shù)體替換函數(shù)的調(diào)用。
6.2 特性查看方式:
- 在release模式下,查看編譯器生成的匯編代碼中是否存在call Add
- 在debug模式下,需要對編譯器進行設置,否則不會展開(因為debug模式下,編譯器默認不 會對代碼進行優(yōu)化,以下給出vs2013的設置方式)
在《C++prime》第五版中關于inline的建議:
內(nèi)聯(lián)說明只是向編譯器發(fā)出一個請求,編譯器可以選擇忽略這個請求。
一般來說,內(nèi)聯(lián)機制用于優(yōu)化規(guī)模較小、流程直接、頻繁調(diào)用的函數(shù)。很多編譯器都不支持內(nèi)聯(lián)遞歸函數(shù),而且一個75行的函數(shù)也不太可能在調(diào)用點內(nèi)聯(lián)展開(75不是編譯器規(guī)定的)。
3.inline不建議聲明和定義分離,分離會導致鏈接錯誤。因為inline被展開,就沒有函數(shù)地址 了,鏈接就會找不到。
注意:
當內(nèi)聯(lián)函數(shù)太長,編譯不會將其在調(diào)用內(nèi)聯(lián)函數(shù)的地方展開;此時函數(shù)相當于一個正常的函數(shù),編譯器給該函數(shù)符號分配地址合成在符號表中,然后通過符號表調(diào)用該函數(shù)。
說明:func是一個很長的函數(shù)。
如上圖所示,當內(nèi)聯(lián)函數(shù)很長時,編譯器不會在調(diào)用內(nèi)聯(lián)函數(shù)的地方展開 ,可以看到內(nèi)聯(lián)函數(shù)會分配一個地址,然后編譯器調(diào)通過地址調(diào)用該內(nèi)聯(lián)函數(shù)。
【面試題】
1. 宏的優(yōu)缺點?
優(yōu)點:
缺點:
2. C++有哪些技術替換宏?
隨著程序越來越復雜,程序中用到的類型也越來越復雜,經(jīng)常體現(xiàn)在:
//這是一個例子
//下面的代碼不一定認識
//但是這是C++的代碼
#include#include
可以看到上述代碼中:
//這是一個類型,但是該類型太長,容易寫錯
std::map::iterator
我們可以使用typedef給類型取別名以簡化代碼,但是typedef有會遇到新的難題:
//如:typedef std::map::iterator iterator;
typedef char* pstring;
int main()
{
const pstring p1; // 編譯成功還是失???
const pstring* p2; // 編譯成功還是失???
return 0;
}
在編程時,常常需要把表達式的值賦值給變量,這就要求在聲明變量的時候清楚地知道表達式的 類型。然而有時候要做到這點并非那么容易,因此C++11給auto賦予了新的含義。
7.2 auto在早期C/C++中auto的含義是:使用auto修飾的變量,是具有自動存儲器的局部變量。
C++11中,標準委員會賦予了auto全新的含義即:auto不再是一個存儲類型指示符,而是作為一 個新的類型指示符來指示編譯器,auto聲明的變量必須由編譯器在編譯時期推導而得。
#includeusing namespace std;
int TestAuto()
{
return 10;
}
//typeid().name() 用來求變量的類型對于的字符串
int main()
{
int a = 10;
auto b = a;
auto c = 'a';
auto d = TestAuto();
cout<< typeid(b).name()<< endl;
cout<< typeid(c).name()<< endl;
cout<< typeid(d).name()<< endl;
//auto e; 無法通過編譯,使用auto定義變量時必須對其進行初始化
return 0;
}
運行程序,可以看到下圖:??
7.3 auto使用細則 ??1. auto與指針和引用結合起來使用【注意】
使用auto定義變量時必須對其進行初始化,在編譯階段編譯器需要根據(jù)初始化表達式來推導auto 的實際類型。因此auto并非是一種“類型”的聲明,而是一個類型聲明時的“占位符”,編譯器在編 譯期會將auto替換為變量實際的類型。
? 用auto聲明指針類型時,用auto和auto*沒有任何區(qū)別,但用auto聲明引用類型時則必須加&。
#includeusing namespace std;
int main()
{
int x = 10;
auto a = &x;
auto* b = &x;
auto& c = x;
cout<< typeid(a).name()<< endl;
cout<< typeid(b).name()<< endl;
cout<< typeid(c).name()<< endl;
*a = 20;
*b = 30;
c = 40;
return 0;
}
2. 在同一行定義多個變量當在同一行聲明多個變量時,這些變量必須是相同的類型,否則編譯器將會報錯,因為編譯 器實際只對第一個類型進行推導,然后用推導出來的類型定義其他變量。
void TestAuto()
{
auto a = 1, b = 2;
auto c = 3, d = 4.0; // 該行代碼會編譯失敗,因為c和d的初始化表達式類型不同
}
上述代碼編譯會出錯,如下圖所示:?
7.4 auto不能推導的場景1. auto不能作為函數(shù)的參數(shù);
auto不能作為形參類型,因為編譯器無法對形參的實際類型進行推導。
2. auto不能直接用來聲明數(shù)組;
3.?為了避免與C++98中的auto發(fā)生混淆,C++11只保留了auto作為類型指示符的用法;
4. auto在實際中最常見的優(yōu)勢用法就是跟以后會講到的C++11提供的新式for循環(huán),還有 lambda表達式等進行配合使用。
八、基于范圍的for循環(huán)(C++11) 8.1 范圍for的語法在C++98中如果要遍歷一個數(shù)組,可以按照以下方式進行:
void TestFor()
{
int array[] = { 1, 2, 3, 4, 5 };
for (int i = 0; i< sizeof(array) / sizeof(array[0]); ++i)
array[i] *= 2;
for (int* p = array; p< array + sizeof(array)/ sizeof(array[0]); ++p)
cout<< *p<< endl;
}
對于一個有范圍的集合而言,由程序員來說明循環(huán)的范圍是多余的,有時候還會容易犯錯誤。因 此C++11中引入了基于范圍的for循環(huán)。for循環(huán)后的括號由冒號“ :”分為兩部分:第一部分是范 圍內(nèi)用于迭代的變量,第二部分則表示被迭代的范圍。
void TestFor()
{
int array[] = { 1, 2, 3, 4, 5 };
for(auto& e : array)
e *= 2;
//注意下面代碼中e是數(shù)組元素的拷貝,改變e不會改變數(shù)組當中的元素
for(auto e : array)
cout<< e<< " ";
}
注意:與普通循環(huán)類似,可以用continue來結束本次循環(huán),也可以用break來跳出整個循環(huán)。??
上述程序同樣可以遍歷數(shù)組,使用引用可以改變數(shù)組的值;
8.2 范圍for的使用條件1. for循環(huán)迭代的范圍必須是確定的;
對于數(shù)組而言,就是數(shù)組中第一個元素和最后一個元素的范圍;對于類而言,應該提供begin? ? ? ? ? 和end的方法,begin和end就是for循環(huán)迭代的范圍。
//注意:以下代碼就有問題,因為for的范圍不確定
void TestFor(int array[])
{
for(auto& e : array)
cout<< e<
2. 迭代的對象要實現(xiàn)++和==的操作。(了解一下就行)?
九、指針空值nullptr(C++) 9.1 C++98中的指針空值在良好的C/C++編程習慣中,聲明一個變量時最好給該變量一個合適的初始值,否則可能會出現(xiàn) 不可預料的錯誤,比如未初始化的指針。如果一個指針沒有合法的指向,我們基本都是按照如下 方式對其進行初始化:
void TestPtr()
{
int* p1 = NULL;
int* p2 = 0;
// ……
}
NULL實際是一個宏,在傳統(tǒng)的C頭文件(stddef.h)中,可以看到如下代碼:?
#ifndef NULL
#ifdef __cplusplus //C++中NULL為0,而不是空指針
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
可以看到,NULL可能被定義為字面常量0,或者被定義為無類型指針(void*)的常量。不論采取何 種定義,在使用空值的指針時,都不可避免的會遇到一些麻煩,比如:?
#includeusing namespace std;
void f(int)
{
cout<<"f(int)"<
程序本意是想通過f(NULL)調(diào)用指針版本的f(int*)函數(shù),但是由于NULL被定義成0,因此與程序的 初衷相悖。
在C++98中,字面常量0既可以是一個整形數(shù)字,也可以是無類型的指針(void*)常量,但是編譯器 默認情況下將其看成是一個整形常量,如果要將其按照指針方式來使用,必須對其進行強轉(void *)0。
在C++中,增加了一個關鍵字 nullptr 表示一個空指針。
注意:
1. 在使用nullptr表示指針空值時,不需要包含頭文件,因為nullptr是C++11作為新關鍵字引入 的。
2. 在C++11中,sizeof(nullptr) 與 sizeof((void*)0)所占的字節(jié)數(shù)相同。?
3. 為了提高代碼的健壯性,在后續(xù)表示指針空值時建議最好使用nullptr。?
你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調(diào)度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧
分享文章:[C++]打開新世界的大門之C++入門-創(chuàng)新互聯(lián)
分享路徑:http://m.rwnh.cn/article46/copihg.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站改版、網(wǎng)站設計公司、App設計、動態(tài)網(wǎng)站、網(wǎng)站建設、品牌網(wǎng)站設計
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容