1. 函數最外層作用域中的局部變量不能使用與函數形參1樣的名字,由于它們屬于同1個作用域范圍.
2. 局部靜態變量的生命周期: 在全部程序的履行路徑第1次經過對象定義語句時初始化,并且直到全部程序終止時才被燒毀,在此期間即便對象所在函數結束履行也不會對它有影響.
3. 如果重載的函數的參數只有頂層const區分,那末是毛病的:
如果有底層const區分可以算作重載.
4. 如果函數的參數要使用援用(且不會改變援用對象的值),那末應當定義成常量援用. 由于使用普通援用參數會限制函數所能接受的實參類型.
上述例子,如果傳遞常量int給函數get(),那末就將出錯.
還有1個更難發覺的毛病,如果A函數正肯定義形參為常量援用,但是B函數仍然定義形參為普通援用,那末在A函數中使用B函數將出錯:
5. 如何給函數傳遞數組形參?
數組也是對象,只不過數組名會自動轉化為首元素指針.數組也是有地址的.數組也是有指針的.數組的指針用*解援用便可得到數組本身.
1維數組:
多維數組: C++實際上沒有多維數組,所謂多維數組不過是數組的數組,所以多維數組的第2維(和后面所有維度)的大小都是數組類型的1部份,不能省略.
問題:為何上面輸出A數組的值要用(*A)[i],而不能直接A[i]輸出?
A是1個指向int[10]數組的指針,那末*A就是1個int[10]的數組.那末(*A)[i]就是這個int[10]數組的第i個元素了.
或可以這么理解其實A是2維數組int a[10][10]的這個a數組中的第1個元素(該元素是1個int[10]數組)的指針,所以*A是a的第1個元素(該元素是1個int[10]數組),所以(*A)[i]是具體的int值元素了.
傳到print()函數中的是a數組首元素(a[0]數組)的指針,所以如果想輸出a[1]的10個元素,需要先A+1,然后*(A+1),然后取每一個元素(*(A+1))[i].
6. 深入討論:首先使用數組名時,會自動將該數組名轉換為該數組首元素的指針. 但是如果我們想使用該數組的指針(而不單單是首元素的指針)該怎樣辦?
數組也是對象,對其用&取地址符就能夠取得它的地址:
7. 對char **A 這類形參,它的含義是甚么?
下面的話“A是1個數組,該數組內都是char*指針”不嚴謹。正確的理解應當是A是1個指向char類型指針的指針。所以我們*A可以得到1個char*指針,至于這個char*指針到底指向1個char數組的元素還是該char*指針僅僅指向1個char還是該char*指針內容根本非法,就不是我們能管的事了,這需要程序的其他部份給予保證。
注意上面程序的實現.
8. 如何給函數傳遞數組援用形參?
數組援用形參要正確寫明數組的所有維度.
9. 不要返回局部變量的援用或指針(雖然測試簡單的程序,這么做常常能得到正確的結果,但是這么做卻是嚴重的毛病):
10. 調用運算符和點運算符,箭頭運算符優先級相同且都符合左結合律,所以如果函數返回指針,援用或類的對象,我們能用函數調用的結果訪問結果對象的成員.
11. C++11支持列表初始化返回值:
12. 函數不能返回數組(由于數組不能被拷貝),函數只能返回數組的指針:
13. 如何直接定義1個返回數組指針的函數?
上面的括號不能少.
14. const_cast用法:
用法:const_cast<type_id>(expression)
該運算符用來修改類型的(底層)const或volatile屬性。除const 或volatile修飾以外, type_id和expression的類型是1樣的。
1、常量指針被轉化成非常量的指針,并且依然指向原來的對象;
2、常量援用被轉換成非常量的援用,并且依然指向原來的對象;
由上面s3可知const_cast<>()強轉還是保持之前的內存地址,
const_cast<>()可使得底層const消失,但是內存地址還是不變的.用了const_cast<>()以后就能夠通過b改變之前內存的內容,但是仍然不能通過a去改變. 援用和指針的底層const用強轉都是1樣的效果.
如果僅用const_cast<>()強轉頂層const是無意義的行動,且編譯不能通過.
本來就是用a的值去賦給b, 就算a轉成int類型,也沒有任何區分.
error: invalid use of const_cast with type'int', which is not a pointer, reference, nor a pointer-to-data-member type.
上面是編譯器的毛病說明. 說明const_cast只能用于指針或援用的底層const.(第3項不知道是甚么?)
15. 如何聲明僅具有局部作用域的函數?
在全局定義,但是在局部作用域聲明函數,便可使得特定函數僅具有局部作用域.main中對print不可見,由于print的定義在main函數后面,且print的聲明在get函數中. 如果print定義在main前面,就算print不聲明,main中也能夠使用print.
16. 函數默許實參,如果函數某個形參有默許值,那末它后面的每一個形參都必須有默許值. 下面是兩種函數定義默許值的方式:
方式1:推薦此方式.
方式2
且如果調用含有默許值的函數,所給出的實參總是優先匹配最左側的形參. 局部變量不能作為默許實參.
17. 只能用全局變量作為默許實參.且默許實參的名字在函數聲明所在的作用域內解析,而這些名字的求值進程產生在函數調用時.
18. const與constexpr 修飾符:
我們已知道了字面值常量的值是不可更改的,所以稱之為常量。變量是內存中的1塊存儲空間,我們可以讀寫里面的內容。但有時候我們也需要1種機制能夠禁止隨便的修改1個變量的值,這時候候我們就要用到const限定符(const-qualifier)。在定義或聲明1個變量的時候,const限定符可以放在我們前面講過的類型說明符前面或后面表示該變量的值不可被更改。要注意的是,如果變量定義或聲明的時候有const限定符,那末1定要進行初始化。由于const變量不可以后來被賦值。對基本數據類型來講,這也是初始化和賦值的1個細微差別:可以初始化1個const變量,但不可以賦值。例如,
const限定符在語法上也是類型說明符的1種,但是他不可單獨使用,必須和其他的類型說明符搭配使用而表明不可改變(constant)的性質。由于const限定符也是類型說明符,所以const變量和非const變量在C++中其實不是同1種類型,雖然他們之間還是有著千絲萬縷的聯系,我們以后會詳細講述。你現在要記住的便是int和const int其實不是同1種類型。
C++還提供了1種更加``嚴格''的constexpr說明符(constexpr-specifier),在變量被聲明或定義的時候,如果類型說明符前面或后面用了constexpr說明符,則表明該變量是1個const變量同時該變量必須被初始化。你或許說,這個const不是1樣么constexpr更加嚴格,用來初始化該變量的表達式必須是1個``常數表達式''。也就是說constexpr變量是1個由常數表達式初始化的const變量。關于常數表達式,我們以后還會詳細談起,對基本數據類型來講,常數表達式是由字面值常量,constexpr限制的變量,和由常數表達式初始化過的const變量組成的表達式。換句話說,常數表達式的值在編譯期間就能夠肯定。
constexpr的變量的值必須是編譯器在編譯的時候就能夠肯定的。上例中由于nonconst_var的值在語法上來說,運行期間可能被更改,所以編譯期間沒法肯定,不屬于常數表達式。由于const_var2是由非常數表達式來初始化的,所以const_var2也不是常數表達式。但const_var2本身的聲明,定義及初始化是合法的。constexpr比const更嚴格,用來初始化constexpr_var2和constexpr_var3的也都不是常數表達式,所以他們的定義都是毛病的。
19. 函數指針及其用法:
當把函數名作為1個值使用時,該函數自動轉化為指針.
聲明具有函數指針形參的函數:
使用typedef簡化函數指針的定義:
C++ primer 第5版中文版 P222⑵23頁有更多內容展開.