諸城市做網(wǎng)站百度問答庫
文章目錄
- 一、引用和指針
- 1.引用
- 2.指針
- 2.1利用指針訪問對象
- 2.2指針的值或指針所指對象的值的改變
- 3.賦值和指針
- 4.指向指針的引用
- 二、String
- 1.初始化String對象的方式
- 2. string對象上的操作
- 3.使用getline讀取一整行
- 4.字面值和字符串相加
- 5.使用for循環(huán)改變字符串中的字符
- 三、Vector
- 1.定義和初始化vector對象
- 四、迭代器
- 標準容器迭代器的運算符
- 迭代器的運算
- 五、數(shù)組
- 初始化
- 理解復雜的數(shù)組聲明
- 數(shù)組和指針
- 六、函數(shù)
- 1.引用傳遞和值傳遞
- 2.傳值參數(shù)
- 指針形參
- 如何使用指針形參交換兩個整數(shù)的值
- 3.傳引用參數(shù)
- 使用引用避免拷貝。當函數(shù)無須修改引用形參的值時最好使用常量引用。
- 使用形參隱式返回額外信息
- 4.數(shù)組形參
- 5.返回數(shù)組指針
- 聲明一個返回數(shù)組指針的函數(shù)
- 6.函數(shù)重載
- 七、類
- 6.函數(shù)重載
- 其他
- Rvalue references 右值引用
- 內(nèi)存管理
- 可變參數(shù)模板 Variadic Templates
- 例一、可變模板參數(shù)(遞歸調(diào)用)
- max函數(shù)比大小
- 處理print函數(shù)
- 例二、遞歸繼承
- 例三、遞歸復合
一、引用和指針
1.引用
? 一般在初始化變量時,初始值會被拷貝到新建的對象中。然而定義引用時,程序把引用和它的初始值綁定(bind)在一起,而不是將初始值拷貝給引用。一旦初始化完成,引用將和它的初始值對象一直綁定在一起。因為無法令引用重新綁定到另外一個對象,因此引用必須初始化。
? 引用并非對象,相反的,它只是為一個已經(jīng)存在的對象所起的另外一個名字。
? 定義了一個引用之后,對其進行的所有操作都是在與之綁定的對象上進行的:
refval = 2; // 把2賦給 refVal 指向的對象,此處即是賦給了ival
int ii = refVal;//與ii=ival執(zhí)行結(jié)果一樣
2.指針
? 指針(pointer)是“指向(point to)”另外一種類型的復合類型。與引用類似,指針也實現(xiàn)了對其他對象的間接訪問。然而指針與引用相比又有很多不同點。其一,指針本身就是一個對象,允許對指針賦值和拷貝,而且在指針的生命周期內(nèi)它可以先后指向幾個不同的對象。其二,指針無須在定義時賦初值。和其他內(nèi)置類型一樣,在塊作用域內(nèi)定義的指針如果沒有被初始化,也將擁有一個不確定的值。
2.1利用指針訪問對象
如果指針指向了一個對象,則允許使用解引用符(操作符*)來訪問該對象:
int ival = 42;
int *p = &ival; //p存放著變量ival的地址,或者說p是指向變量ival的指針
cout << *p; // 由符號*得到指針p所指的對象,輸出 42
對指針解引用會得出所指的對象,因此如果給解引用的結(jié)果賦值,實際上也就是給指針既指的對象賦值:
*p = 0; // 由符號*得到指針p所指的對象,即可經(jīng)由P為變量ival賦值
cout << *p; //輸出0如上述程序所示,為*p賦值實際上是為p所指的對象賦值。
<!--解引用操作僅適用于那些確實指向了某個對象的有效指針。-->
2.2指針的值或指針所指對象的值的改變
? 有時候要想搞清楚一條賦值語句到底是改變了指針的值還是改變了指針所指對象的值不太容易,最好的辦法就是記住賦值永遠改變的是等號左側(cè)的對象。當寫出如下語句時:
pi = &ival; // pi 的值被改變,現(xiàn)在pi 指向了ival
? 意思是為pi 賦一個新的值,也就是改變了那個存放在pi內(nèi)的地址值。相反的,如果寫出如下語句:
*pi = 0; // ival的值被改變,指針pi并沒有改變
? 則*pi(也就是指針pi指向的那個對象)發(fā)生改變。
3.賦值和指針
? 指針和引用都能提供對其他對象的間接訪問,然而在具體實現(xiàn)細節(jié)上二者有很大不同,其中最重要的一點就是引用本身并非一個對象。一旦定義了引用,就無法令其再綁定到另外的對象,之后每次使用這個引用都是訪問它最初綁定的那個對象。
? 指針和它存放的地址之間就沒有這種限制了。和其他任何變量(只要不是引用)一樣,
? 給指針賦值就是令它存放一個新的地址,從而指向一個新的對象:
int i =42;
int *pi =0; //pi被初始化,但沒有指向任何對象
int *pi2 = &i; //pi2被初始化,存有i的地址
int *pi3; //如果pi3定義于塊內(nèi),則pi3的值是無法確定的pi3= pi2; //pi3和pi2指向同一個對象i
pi2 = 0; //現(xiàn)在pi2不指向任何對象了
4.指向指針的引用
? 引用本身不是一個對象,因此不能定義指向引用的指針。但指針是對象,所以存在
指向指針的引用:
int i=42;
int *pi ; // p是一個int型指針
int *&r =pi; //r是一個對指針p的引用r = &i; //r引用了一個指針,因此給上賦值&i就是令p指向i
*r =0; //解引用r得到i,也就是p指向的對象,將i的值改為0
? 要理解r的類型到底是什么,最簡單的辦法是從右向左閱讀r的定義。離變量名最近的符號(此例中是&r的符號&)對變量的類型有最直接的影響,因此r是一個引用。聲明符的其余部分用以確定r引用的類型是什么,此例中的符號*說明r引用的是一個指針。最后,聲明的基本數(shù)據(jù)類型部分指出r引用的是一個int指針。
二、String
1.初始化String對象的方式
string s1 //默認初始化,s1是一個字符串
string s2(s1) //s2是s1的副本
string s2 == s1 //等價于上面
string s3("value") //s3是字面值value的副本,除了最后一個空字符外
string s3 = "value" //等價于上面
string s4(n,'c') //n個連續(xù)的c組成的串
2. string對象上的操作
os<<s //將s寫到輸出流os當中,返回os
is>>s //從is中讀取字符串賦給s,字符串以空白分隔,返回is
getline(is, s)//從is中讀取一行賦給s,返回is
s.empty() //s為空返回true,否則返回false
s.size() //返回s中字符的個數(shù)
s[n] //返回s中第n個字符的引用,位置n從0計起
s1+s2 //返回s1和s2連接后的結(jié)果
sl=s2 //用s2的副本代替s1中原來的字符
s1==s2 //如果s1和s2中所含的字符完全一樣,則它們相等;string對象的相
s1!=s2 //等性判斷對字母的大小寫敏感
<,<=,>,>= //利用字符在字典中的順序進行比較,且對字母的大小寫敏感
? 第1章曾經(jīng)介紹過,使用標準庫中的 iostream 來讀寫int、double等內(nèi)置類型的值。同樣,也可以使用IO操作符讀寫string對象:
//注意:要想編譯下面的代碼還需要適當?shù)?include語句和using聲明
int main()
{string s;cin >> s; //如果程序的輸入是“ Hello World! "cout << s << endl; //則輸出將是“Hello”,輸出結(jié)果中沒有任何空格。return 0;
}
?
string s1, s2; // 把第一個輸入讀到 s1 中,第二個輸入讀到 s2 中
cin >> s1 >> s2; //輸出兩個 string對象
cout << s1 << s2 << endl;//輸出HelloWorld!
3.使用getline讀取一整行
? 有時我們希望能在最終得到的字符串中保留輸入時的空白符,這時應該用 getline函數(shù)代替原來的>>運算符。getline函數(shù)的參數(shù)是一個輸入流和一個string對象,函數(shù)從給定的輸入流中讀入內(nèi)容,直到遇到換行符為止(注意換行符也被讀進來了),然后把所讀的內(nèi)容存入到那個string對象中去(注意不存換行符)。getline只要一遇到換行符就結(jié)束讀取操作并返回結(jié)果,哪怕輸入的一開始就是換行符也是如此。如果輸入真的一開始就是換行符,那么所得的結(jié)果是個空string。
和輸入運算符一樣,getline 也會返回它的流參數(shù)。因此既然輸入運算符能作為判斷的條件(Ctrl+D/Z),我們也能用getline 的結(jié)果作為條件。例如,可以通過改寫之前的程序讓它一次輸出一整行,而不再是每行輸出一個詞了:
int main()
{string line; //每次讀入一整行,直至到達文件末尾while (getline(cin, line))cout << line << endl;return 0;
}
? 因為line中不包含換行符,所以我們手動地加上換行操作符。和往常一樣,使用end1結(jié)束當前行并刷新顯示緩沖區(qū)。
4.字面值和字符串相加
string s4 = s1 + ","; //正確;把一個string對象和一個字面值相加
string s5 = "hello" + ","; //錯誤;兩個運算的對象都不是string
string s6 = s1 + "hello" + "," ;//正確;每個加法運算符都有一個string對象
string s7 = "hello" + "," + s1; //錯誤;不能將兩個字面值相加
5.使用for循環(huán)改變字符串中的字符
string s("Hello World!!!");//轉(zhuǎn)換成大寫形式。
for (auto &c :s) // 對于s中的每個字符(注意:C是引用)c = toupper(c); //c是一個引用,因此賦值語句將改變s中字符的值cout << s << endl;
使用下標執(zhí)行迭代
另一個例子是把s的第一個詞改成大寫形式:
//依次處理s中的字符直至我們處理完全部字符或者遇到一個空白
for (decltype(s.size())index =0; index != s.size() && !isspace(s[index]); ++index)s[index] = toupper(s[index]); //將當前字符改成大寫形式
//index的類型是由 decltype關鍵字決定的,保證下標小于size()的值就可以了。
三、Vector
1.定義和初始化vector對象
vector<T> vl //v1是一個空vector,它潛在的元素是T類型的,執(zhí)行默認初始化
vector<T> v2(v1) //v2中包含有v1所有元素的副本
vector<T> v2 = vl //等價于v2(v1),v2中包含有v1所有元素的副本
vector<T> v3(n, val)//v3包含了n個重復的元素,每個元素的值都是val
vector<T> v4(n) //v4包含了n個重復地執(zhí)行了值初始化的對象
vector<T> v5{a,b,c.} //v5包含了初始值個數(shù)的元素,每個元素被賦予相應的初始值
vector<T> v5 = {a,b, c.} //等價于v5{a,b,c...}
四、迭代器
標準容器迭代器的運算符
*iter 返回迭代器iter所指元素的引用
iter->mem 解引用iter并獲取該元素的名為mem的成員,等價于(*iter).mem
++iter 令iter指示容器中的下一個元素
--iter 令iter指示容器中的上一個元素
iterl == iter2 判斷兩個迭代器是否相等(不相等),如果兩個迭代器指示的是同一個元
iterl != iter2 素或者它們是同一個容器的尾后迭代器,則相等;反之,不相等
? 和指針類似,也能通過解引用迭代器來獲取它所指示的元素,執(zhí)行解引用的迭代器必須合法并確實指示著某個元素。試圖解引用一個非法迭代器或者尾后迭代器都是未被定義的行為。
讀取text文本數(shù)據(jù):
// 依次輸出 text 的每一行直至遇到第一個空白行為止
for (auto it = text.cbegin();it != text.cend() && !it->empty();++ it)cout << *it << endl;
迭代器的運算
二分查找法
auto mid = vi.begin() + vi.size()/2
五、數(shù)組
初始化
我們可以用字符串字面值對此類數(shù)組初始化。當使用這種方式時,一定要注意字符串字面值的結(jié)尾處還有一個空字符,這個空字符也會像字符串的其他字符一樣被拷貝到字符數(shù)組中去:
char al[l] = {'c','+'} // 列表初始化,沒有空字符
char a2[] = {'c','+','\0'} //列表初始化,含有顯式的空字符
char a3[] = "C++" //自動添加表示字符串結(jié)束的空字符
const char a4[6] = "Daniel"; //錯誤:沒有空間可存放空字符!
盡管字符串字面值"Daniel"看起來只有6個字符,但是數(shù)組的大小必須至少是7,其中6個位置存放字面值的內(nèi)容,另外1個存放結(jié)尾處的空字符。
不能將數(shù)組的內(nèi)容拷貝給其他數(shù)組作為其初始值,也不能用數(shù)組為其他數(shù)組賦值:
int a[] = {1,2,3};
int a2[] = a; //err
a2 = a; //err
理解復雜的數(shù)組聲明
int *ptrs[10];
int (*Parray)[10] = &arr;
int (&arrRef)[10] = arr;
默認情況下,類型修飾符從右向左依次綁定。對于ptrs來說,從右向左(參見2.3.3節(jié),第52頁)理解其含義比較簡單:首先知道我們定義的是一個大小為10的數(shù)組,它的名字是ptrs,然后知道數(shù)組中存放的是指向int的指針。
但是對于Parray來說,從右向左理解就不太合理了。因為數(shù)組的維度是緊跟著被聲明的名字的,所以就數(shù)組而言,由內(nèi)向外閱讀要比從右向左好多了。由內(nèi)向外的順序可幫助我們更好地理解Parray 的含義:首先是圓括號括起來的部分,*Parray 意味著Parray是個指針,接下來觀察右邊,可知道Parray 是個指向大小為10的數(shù)組的指針,最后觀察左邊,知道數(shù)組中的元素是int。這樣最終的含義就明白無誤了,Parray是一個指針,它指向一個 int 數(shù)組,數(shù)組中包含 10個元素。同理,(&arrRef)表示arrRef是一個引用,它引用的對象是一個大小為10的數(shù)組,數(shù)組中元素的類型是int.
*
當然,對修飾符的數(shù)量并沒有特殊限制:
int*(&arry)[10]-ptrs;// arry是數(shù)組的引用,該數(shù)組含有10個指針
按照由內(nèi)向外的順序閱讀上述語句,首先知道arry是一個引用,然后觀察右邊知道,arry引用的對象是一個大小為10的數(shù)組,最后觀察左邊知道,數(shù)組的元素類型是指向int的、指針。這樣,arry就是一個含有10個int型指針的數(shù)組的引用。
要想理解數(shù)組聲明的含義,最好的辦法是從數(shù)組的名字開始按照由內(nèi)向外的順序閱讀。
數(shù)組和指針
? 數(shù)組的元素也是對象,對數(shù)組使用下標運算符得到該數(shù)組指定位置的元素。因此像其他對象一樣,對數(shù)組的元素使用取地址符就能得到指向該元素的指針:
string nums[] =("one","two","three"};//數(shù)組的元素是string對象
string *p= &nums[0]; //p指向nums的第一個元素//然而,數(shù)組還有一個特性:在很多用到數(shù)組名字的地方,編譯器都會自動地將其替換為一個指向數(shù)組首元素的指針:
string *p2 = nums;//等價于p2 = &nums[0]
++p2; //p2指向nums[2]
由上可知,在一些情況下數(shù)組的操作實際上是指針的操作,這一結(jié)論有很多隱含的意思。其中一層意思是當使用數(shù)組作為一個auto變量的初始值時,推斷得到的類型是指針而非數(shù)組(decltype可避免):
int ia[]= (0,1,2,3,4,5,6,7,8,9}; // ia是一個含有10個整數(shù)的數(shù)組
auto ia2(ia); // ia2 是一個整型指針,指向ia的第一個元素
ia2 = 42; // 錯誤:ia2是一個指針,不能用int 值給指針賦值
指針也是迭代器
六、函數(shù)
1.引用傳遞和值傳遞
和其他變量一樣,形參的類型決定了形參和實參的交互的方式。如果形參是引用類型,他將綁定到對應的形參上;否則,將實參的值拷貝后賦給形參,形參和實參是兩個獨立的對象。
2.傳值參數(shù)
指針形參
指針的行為和其他非引用類型一樣。當執(zhí)行指針拷貝操作時,拷貝的是指針的值。拷貝之后,兩個指針是不同的指針。因為指針使我們可以間接地訪問它所指的對象,所以通過指針可以修改它所指對象的值:
int n = 0,i=42;
int *p= &n, *q= &i; //p指向n;q指向主
*p=42; //n的值改變;P不變
P=q; //p現(xiàn)在指向了主;但是主和n的值都不變
指針形參的行為與之類似:
//該函數(shù)接受一個指針,然后將指針所指的值置為0
void reset(int *ip)
{*ip=0; //改變指針ip所指對象的值ip=0; //只改變了ip的局部拷貝,實參未被改變
}
調(diào)用reset 函數(shù)之后,實參所指的對緣被置為0,但是實參本身并沒有改變:
int i=42;
reset(&i); //改變主的值而非土的地址
cout << "i" << i << endl; //輸出i=0
如何使用指針形參交換兩個整數(shù)的值
#include <iostream>
using namespace std;
int swap(int *a,int *b);
int main()
{int *p,*q;int min=10;int max=20;p=&min; q=&max; cout<<"交換前:a= "<<min<<",b= "<<max<<endl;swap(p,q);cout<<"交換后:a= "<<min<<",b= "<<max<<endl;return 0;
}
int swap(int *a,int *b)
{int c;c=*a;*a=*b;*b=c;
}
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-R6OUs0vx-1691733924503)(C:\Users\lijiale\AppData\Roaming\Typora\typora-user-images\image-20230718110415925.png)]
p和q分別是兩個數(shù)的地址,通過對地址取內(nèi)容,從而得到該數(shù)的值,交換的時候也應該是將指針指向的數(shù)進行交換。但是但是如果寫成下面的形式,就無法進行交換。
#include <iostream>
using namespace std;
int swap(int *a,int *b);
int main()
{int *p,*q;int min=10;int max=20;p=&min;q=&max; cout<<"交換前:a= "<<min<<",b= "<<max<<endl;swap(p,q);cout<<"交換后:a= "<<min<<",b= "<<max<<endl;return 0;
}
int swap(int *a,int *b)
{int *c;c=a;a=b;b=c;
}
這是因為在swap函數(shù)體內(nèi)部,只是交換了兩個形參指針本身的值,未能影響實參。這時候如果在形參里面也有一條打印語句的話,能夠清晰的看到在被調(diào)函數(shù)里面,確實交換了指針的值,但是這只在局部范圍內(nèi)有效,調(diào)用完畢回到主函數(shù)就失效了。
3.傳引用參數(shù)
通過使用引用形參,允許函數(shù)改變一個或多個實參的值。
使用引用避免拷貝。當函數(shù)無須修改引用形參的值時最好使用常量引用。
bool isShorter(const string &s1,const string &s2)
{return s1.size() < s2.size();
}
使用形參隱式返回額外信息
一種方法是定義一個新的數(shù)據(jù)類型,讓它包含位置和數(shù)量兩個成員。還有另一種更簡單的方法,我們可以給函數(shù)傳入一個額外的引用實參,令其保存字符出現(xiàn)的次數(shù):
//返回s中c第一次出現(xiàn)的位置索引
//引用形參occurs負責統(tǒng)計c出現(xiàn)的總次數(shù)
string::size _type find char(const string &s, char c,string::size _type &occurs)
{auto ret = s.size(); // 第一次出現(xiàn)的位置(如果有的話)occurs = 0; //設置表示出現(xiàn)次數(shù)的形參的值for (decltype(ret) i = 0;!= S.size();++i) {if (s[il == c){if (ret == S.size())ret = i; //記錄c第一次出現(xiàn)的位置++occurs; //將出現(xiàn)的次數(shù)加1}}
return ret; //出現(xiàn)次數(shù)通過occurs 隱式地返回
}
當我們調(diào)用find_char 函數(shù)時,必須傳入三個實參:作為查找范圍的一個 string 對像要找的字符以及一個用于保存字符出現(xiàn)次數(shù)的 size_type。
4.數(shù)組形參
int a[] = {0,1,2}; //含有3個整數(shù)的數(shù)組
int a2[]=a ; //錯誤:不允許使用一個數(shù)組初始化另一個數(shù)組
a2 = a; //錯誤:不能把一個數(shù)組直接賦值給另一個數(shù)組
所以無法以值傳遞的方式使用數(shù)組參數(shù)。
但因為數(shù)組會被轉(zhuǎn)換成指針,所以當我們?yōu)楹瘮?shù)傳遞一個數(shù)組時,實際上傳遞的是指向數(shù)組首元素的指針。
盡管不能以值傳遞的方式傳遞數(shù)組,但是我們可以把形參寫成類似數(shù)組的形式:
//盡管形式不同,但這三個print 函數(shù)是等價的
//每個函數(shù)都有一個const int*類型的形參
void print(const int*);
void print(const int []); //可以看出來,函數(shù)的意圖是作用于一個數(shù)組
void print(const int[10]); // 這里的維度表示我們期望數(shù)組含有多少元素,實際不一定
//盡管表現(xiàn)形式不同,但上面的三個函數(shù)是等價的:每個函數(shù)的唯一形參都是const int*類型的。當編譯器處理對 print 函數(shù)的調(diào)用時,只檢查傳入的參數(shù)是否是const int*類型:
int i=0,j[2] ={0,1);
print(&i); // 正確:&i的類型是int*
print(j); // 正確:j轉(zhuǎn)換成 int*并指向j[0]
如果我們傳給print 函數(shù)的是一個數(shù)組,則實參自動地轉(zhuǎn)換成指向數(shù)組首元素的指針,數(shù)組的大小對函數(shù)的調(diào)用沒有影響。
5.返回數(shù)組指針
因為數(shù)組不能被拷貝,所以函數(shù)不能返回數(shù)組。不過,函數(shù)可以返回數(shù)組的指針或引用(參見五、復雜)。雖然從語法上來說,要想定義一個返回數(shù)組的指針或引用的函數(shù)比較煩瑣,但是有一些方法可以簡化這一任務,其中最直接的方法是使用類型別名:
typedef int arrT[10];// arrT是一個類型別名,它表示的類型是含有10個整數(shù)的數(shù)組
using arrT = int[10];// arrT的等價聲明
arrT* func(int i); //func返回一個指向含有10個整數(shù)的數(shù)組的指針
其中arrT 是含有10個整數(shù)的數(shù)組的別名。因為我們無法返回數(shù)組,所以將返回類型定義成數(shù)組的指針。因此,func 函數(shù)接受一個int 實參,返回一個指向包含10個整數(shù)的數(shù)組的指針。
聲明一個返回數(shù)組指針的函數(shù)
要想在聲明func時不使用類型別名,我們必須牢記被定義的名字后面數(shù)組的維度:
int arr[10];// arr是一個含有10個整數(shù)的數(shù)組
int *pl[10];//p1是一個含有10個指針的數(shù)組
int (*p2)[10] = &arr;//p2是一個指針,它指向含有10個整數(shù)的數(shù)組
和這些聲明一樣,如果我們想定義一個返回數(shù)組指針的函數(shù),則數(shù)組的維度必須跟在函數(shù)名字之后。然而,函數(shù)的形參列表也跟在函數(shù)名字后面且形參列表應該先于數(shù)組的維度。因此,返回數(shù)組指針的函數(shù)形式如下所示:
Type (*function (parameter _list) ) [dimension]
類似于其他數(shù)組的聲明,Type 表示元素的類型,dimension 表示數(shù)組的大小。(*function(parameter _list))兩端的括號必須存在,就像我們定義p2時兩端必須有括號一樣。如果沒有這對括號,函數(shù)的返回類型將是指針的數(shù)組。
舉個具體點的例子,下面這個func函數(shù)的聲明沒有使用類型別名:
int (*func(int i))[10];
可以按照以下的順序來逐層理解該聲明的含義:
func(int i)表示調(diào)用func函數(shù)時需要一個int類型的實參。
(*func(int i))意味著我們可以對函數(shù)調(diào)用的結(jié)果執(zhí)行解引用操作。
(*func (int i))[10]表示解引用func的調(diào)用將得到一個大小是10的數(shù)組。
int (*func (int i))[10] 表示數(shù)組中的元素時int類型
改進:尾置返回類型
auto func(int i) -> int(*)[10];
6.函數(shù)重載
不允許兩個函數(shù)除了返回類型外其他所有要素都相同。
七、類
一個const成員函數(shù)如果以引用的形式返回*this,,那么它的返回類型將是常量引用。
的聲明,Type 表示元素的類型,dimension 表示數(shù)組的大小。(*function(parameter _list))兩端的括號必須存在,就像我們定義p2時兩端必須有括號一樣。如果沒有這對括號,函數(shù)的返回類型將是指針的數(shù)組。
舉個具體點的例子,下面這個func函數(shù)的聲明沒有使用類型別名:
int (*func(int i))[10];
可以按照以下的順序來逐層理解該聲明的含義:
func(int i)表示調(diào)用func函數(shù)時需要一個int類型的實參。
(*func(int i))意味著我們可以對函數(shù)調(diào)用的結(jié)果執(zhí)行解引用操作。
(*func (int i))[10]表示解引用func的調(diào)用將得到一個大小是10的數(shù)組。
int (*func (int i))[10] 表示數(shù)組中的元素時int類型
改進:尾置返回類型```c++
auto func(int i) -> int(*)[10];
6.函數(shù)重載
不允許兩個函數(shù)除了返回類型外其他所有要素都相同。
一個const成員函數(shù)如果以引用的形式返回*this,,那么它的返回類型將是常量引用。
因為非常量版本的函數(shù)對于常量對象是不可用的,所以只能在一個常量對象上調(diào)用const成員函數(shù)。
其他
Rvalue references 右值引用
非必要的拷貝 unnecessary copying = steal 偷
右值:
//int實驗
a + b = 42;//err
//string實驗
string s1("Hello");
string s2("World");
s1 + s2 = s2;//pass,s1 = Hello,s2 = World
string() = "World";//pass 臨時對象也是右值
//complex實驗
complex<int> c1(3,8),c2(1,0);
c1 + c2 = complex<int>(4,9); //pass,c1:(3,8),c2:(1,0)
complex<int>() = complex<int>(4,9);//pass
不可對右值進行操作:
foo()返回的是值(int),在對右值進行取地址操作&foo(),是不允許的
用法:
對于insert操作,提供了兩個函數(shù):
1.copy
insert(...,&x) //x是普通的值
2.move
insert(...,&&x) //x是右值(臨時對象),此時取右值引用
由于vector放的是Mystring,于是class Mystring 有兩個構(gòu)造ctor: move是淺拷貝
深拷貝與淺拷貝:
內(nèi)存管理
可變參數(shù)模板 Variadic Templates
例一、可變模板參數(shù)(遞歸調(diào)用)
max函數(shù)比大小
處理print函數(shù)
例二、遞歸繼承
處理的是類型(type),使用的是class template