平面設計可以做網(wǎng)站湖北最新消息
🌟 Hello,我是egoist2023!
🌍 種一棵樹最好是十年前,其次是現(xiàn)在!
目錄
輸入&輸出
缺省參數(shù)(默認參數(shù))
函數(shù)重載
引用
概念及定義
特性及使用
const引用
與指針的關系
內(nèi)聯(lián)inline和nullptr
inline
nullptr
輸入&輸出
前文了解到本賈尼認為C語言是有缺陷的,想彌補其缺陷,最后搞出自己的一套C++體系。其實,C語言的scanf和printf函數(shù)是有缺陷且過于冗雜(每次都需要手動指定格式),是否能通過一種方式使輸入輸出更簡便呢?針對此問題在C++中引入了輸入&輸出流。
- <iostream> (全稱:?Input Output Stream )是標準的輸入、輸出流庫,定義了標準的輸入、輸出對象。
- std::cin 是 istream 類的對象,它主要面向窄字符的標準輸入流。(C++標準庫都封在std的命名空間中)
- std::cout 是 ostream 類的對象,它主要面向窄字符的標準輸出流。
- std::endl 是?個函數(shù),流插入輸出時,相當于插入一個換行字符加刷新緩沖區(qū)(簡單看成C語言中的\n)。
- <<是流插入運算符,>>是流提取運算符。(在C語言還充當左移/右移位運算符)。
- 輸入輸出可以自動識別變量類型(本質(zhì)是通過函數(shù)重載實現(xiàn)的),最重要的是 C++的流能更好的支持自定義類型對象的輸入輸出。
#include<iostream>
#include<stdio.h>int main()
{int a = 1;std::cout << a;printf("%d", a);return 0;
}
- IO流涉及類和對象,運算符重載、繼承等很多面向?qū)ο蟮闹R,因此在此章節(jié)只介紹IO流的用法。
- 在vs編譯器中<iostream>間接包含了<stdio.h>,因此可以使用printf。
#include<iostream>int main()
{int a = 1;std::cout << a;printf("%d", a);return 0;
}
缺省參數(shù)(默認參數(shù))
- 缺省參數(shù)是聲明或定義函數(shù)時為函數(shù)的參數(shù)指定一個缺省值。在調(diào)用該函數(shù)時,如果沒有指定實參則采用該形參的缺省值。
- 缺省參數(shù)分為全缺省(全部形參給缺省值)和半缺省參數(shù)(部分形參給缺省值)。
- C++規(guī)定半缺省參數(shù)必須從左往右依次連續(xù)缺省,不能間隔給缺省值。(同理依次給實參)
- 函數(shù)聲明和定義分離時,缺省參數(shù)不能在函數(shù)聲明和定義中同時出現(xiàn),規(guī)定必須函數(shù)聲明給缺省值。(這樣做的目的是避免沖突,因為編譯器在鏈接時會合成制表符,此時,聲明和定義都有缺省值就會產(chǎn)生沖突)
-
缺省參數(shù)的意義遠不止如此,在之前的棧和隊列章節(jié)中,棧的初始化中capacity默認開始為0。若一開始明確插入1000個數(shù)據(jù)時,初始化時直接開好,避免多次擴容損失效率。(沒有傳參時會采用缺省參數(shù)的值。)
函數(shù)重載
在C語言中若要實現(xiàn)Add函數(shù)(需要支持整形、浮點型相加)時,需要保證Add函數(shù)名字不沖突,為了解決這一困擾。在C++中,添加了函數(shù)重載這個概念,其要求這些同名函數(shù)的形參不同,可以是參數(shù)個數(shù)不同或者類型不同(不支持返回類型不同),呈現(xiàn)多態(tài)行為,使用更加方便。函數(shù)支持三種類型的重載。
函數(shù)重載是C++中實現(xiàn)多態(tài)性的一種重要方式,具有重要意義(增強了代碼的可讀性,函數(shù)的通用性和復用性),同時為之后的模板(函數(shù)重載的支持)、運算符重載做了鋪墊。
參數(shù)類型不同
int Add(int x, int y)
{cout << "int Add(int x, int y)" << endl;return x + y;
}double Add(double x, double y)
{cout << "double Add(double x, double y)" << endl;return x + y;
}
參數(shù)個數(shù)不同
void f()
{cout << "f()" << endl;
}
void f(int a)
{cout << "f(int a)" << endl;
}
參數(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;
}
引用
概念及定義
引用是給已存在變量取一個別名,語法層面上編譯器不會為其開辟內(nèi)存空間, 它和引用的變量共用同一塊內(nèi)存空間。(實際底層實現(xiàn)上開辟了空間,是用一個指針指向其引用的變量)


特性及使用
? 引用在定義時 必須初始化
? 支持多次引用? 引用一個實體,其別名再不能引用其他實體
- 實踐中,引用傳參和引用做返回值中減少拷貝提高效率和改變引用對象時同時改變被引用對象。
- 使用C++引用替代指針傳參,目的是簡化程序,避開復雜的指針。
- 引用傳參和引用作返回值在實踐中經(jīng)常用到,達到了減少拷貝提高效率(指針也可以減少拷貝)和改變引用對象的目的。(針對自定義類型更為明顯)
在指針章節(jié)中要求交換兩個變量,涉及到傳址調(diào)用(形參改變實參)。同樣,使用引用也可以達到此目的。
const引用
變量也有被const修飾的情況,此時對其進行引用會報錯(權限被放大了),因此需要引入 const引用。
權限要點? -- >? 權限可以平移或者縮小,但一定不能放大。
- 引用一個const對象,必須用const引用。const引用也可以引用普通對象,因為對象的訪問權限可以縮小,不能放大。
- 需要注意的是?int& rb = a*3; double d = 12.34; int& rd = d?這種場景下需要使用const引用
這里涉及到類型轉(zhuǎn)換,將double轉(zhuǎn)換為int&為何需要使用const引用呢?
在類型轉(zhuǎn)換中,會產(chǎn)生臨時對象(也稱未命名對象),這個對象具有常性,此時rb和rd都是引用這個臨時變量,權限被放大了,因此會出現(xiàn)報錯。
- ?臨時對象是編譯器需要一個空間暫存表達式的求值結(jié)果時臨時創(chuàng)建的一個未命名的對象。
與指針的關系
由上文可以發(fā)現(xiàn)引用與指針的部分功能是類似的,那為什么本賈尼還引入了引用這個語法呢?
引?和指針在實踐中相輔相成,功能有重疊性,但是各有特點,互相不可替代。如:C++引?定義后不能改變指向,相反地指針可以改變指向(鏈表章節(jié)中指針定義的結(jié)構(gòu)是不能用引用替代的)。
引用 | 指針 |
語法上不開空間 | 要開空間存儲變量地址 |
必須初始化 | 非必須初始化 |
不能改變指向 | 可以改變指向 |
可以直接訪問指向?qū)ο?/td> | 需要借助*訪問指向?qū)ο?/td> |
引用結(jié)果為引用類型大小 | 看32位/64位平臺 |
\ | 野指針和空指針問題 |
內(nèi)聯(lián)inline和nullptr
inline
inline修飾的函數(shù)叫做內(nèi)聯(lián)函數(shù),編譯時C++編譯器會在調(diào)用的地方展開內(nèi)聯(lián)函數(shù),這樣調(diào)用內(nèi)聯(lián)函數(shù)就需要建立棧幀了,就可以提高效率。
#define Add(x,y) ((x)+(y))
inline int Add(const int& x, const int& y)
{
? ? return x + y;
}
在實現(xiàn)Add函數(shù)中使用define宏定義時需要考慮各種因素,而使用inline則無需顧慮很多,讓編譯器決定是否展開此函數(shù)。
- inline對于編譯器是一個建議(選擇性展開),適用于頻繁調(diào)用的短小函數(shù),對于遞歸函數(shù),代碼相對多一些的函數(shù),加上inline也會被編譯器忽略。
- inline不建議聲明和定義分離到兩個文件 ,分離會導致鏈接錯誤。因為inline被展開,就沒有函數(shù)地址,鏈接時會出現(xiàn)報錯(不能合成制表符)。
- vs編譯器 debug版本下面默認是不展開inline的,因此需要設置下。
nullptr
引入nullptr實際是為了替代C語言的NULL(有缺陷)。
NULL實際是一個宏,在頭文件(stddef.h)中。
#ifndef NULL#ifdef __cplusplus#define NULL 0#else#define NULL ((void *)0)#endif
#endif
C++中NULL可能被定義為 常量0 ,或者C中被定義為 無類型指針(void*) 的常量。但都不可避免的會遇到一些麻煩。nullptr(關鍵字)是?種特殊類型的字面量,它可以轉(zhuǎn)換成任意其他類型的指針類型。使用 nullptr定義空指針可以避免類型轉(zhuǎn)換 的問題。(nullptr只能被隱式地轉(zhuǎn)換為指針類型,而不能被轉(zhuǎn)換為整數(shù)類型)
若NULL為無類型指針(void*)呢?運行后會報錯,這是因為2個函數(shù)重載中沒有一個能轉(zhuǎn)換所有參數(shù)類型。
#include<iostream>
using namespace std;void f(int x)
{cout << "f(int x)" << endl;
}void f(int* ptr)
{cout << "f(int* ptr)" << endl;
}int main()
{f(NULL);//調(diào)用f(int x)f(nullptr);//調(diào)用f(int* ptr)f((void*)0);//errreturn 0;
}