1,介紹main函數的意義和其基本結構,return語句。不同平台下編譯與執行程序。
2,兩個類isrteam與otream與它們的實例對象cin,cout,cerr,clog。說明了程序中基本的輸入與輸出。“<<”與”>>”作為操作符,左操作符是一個iostream 對象,右操作符是一個變量。返回值仍為一個iostream對象,所以輸入或輸出可以這樣 cout<<”a=”<<a<<endl 連著寫。
3,C++中的兩種注釋風格以及需要注意的問題。
4,控制結果:循環(while與for),選擇(if…else…)。引入一個計算兩個數之間所有整數的和例子。
5,C++最重要的特性:類。說明了在類上定義的一些操作,簡單介紹成員函數,用“.”來調用成員函數。
6,書的開頭引入的一個書店書目的問題,用一個完整的程序,進一步說明了C++程序中的一些基本元素。當然Scales_item並沒有具體的實現代碼。
1,執行算術運算時,數據類型的選擇:short 一般很少使用,容易產生越界。char類型在一些實現中有時作為signed處理,而有時作為unsigned處理,所以只用char來表示字符是明智之舉。所以在大多數的時候使用int就沒有問題,在很多機器上int用4個字節存儲,足夠滿足大部分計算的要求。浮點型的選擇就很簡單了,使用double類型基本不會有什麼錯誤,而且有可能會比float計算代價低。
2,字面值常量。只有內置類型存在字面值。寬字符的類型wchar_t,其實字面值字符常量前面加一個“L”,如wchar_t c=L’A’;多行字符串可以用‘\’進行連接,但是\後面不可以有任何空格或制表符,下一行字符串字面值前也不可以有任何空格和制表符。
3,介紹了變量的概念,變量名的命名規范:1)變量名一般用小寫字母;2)標識符最好有意義;3)多個詞之間用下劃線或內嵌的單詞第一個字母大寫。另外,標識符不要以兩個連續的下劃線或下劃線+大寫字母命名。
4,定義對象(變量定義)。變量在定義的時候可以進行初始化,可以選擇復制初始化(不要理解為了賦值),也可以選擇直接初始化。
5,定義與聲明的區別;注意extern的使用。
6,const限定符的用法。const 定義的變量不能修改,所以必須在定義的時候進行初始化。const變量如果想在多文件中使用,必須在定義的時候就聲明為外部變量,即用extern。
7,引入與const。
1)非cosnt引用只能綁定到與該引用同類型的對象。
2)const引用則可以綁定到不同但相關的類型的對象或綁定到右值。
8,枚舉類型enum。
9,struct與class在創建類時的區別:struct的默認訪問級別為public,而class的則為private。
10,說明了C++語言頭文件的使用與編寫,以及使用定義預處理器變量來避免頭文件的重復包含。
1,命名空間的using聲明
using std::string
2,標准庫string類型
標准庫string類型。string類型和字符串字面值不是同一種類型,注意幾種string的構造函數。
用cin讀取string類型時,讀取並忽略開頭所有的空白字符,直至再次遇到空白字符,讀取終止。
getline可以讀取輸入流中的一行,但是不包括換行符。
在string對象比較時,小寫字母都比大寫字母要大,即大寫字母排在前面。
string對象的下標是從0開始到s.size()-1為止。
3,標准庫vector類型
C++程序員習慣於優先使用!=而不是<來編寫循環判斷條件。for(string::size_type i=0; i != s.size(); i++)
C++編譯器遇到內聯函數時,都是直接擴展相應的代碼,而不是實際的函數調用,所以像size這樣的小庫函數在循環中調用它代價是很小的。
4,迭代器簡介
每一種容器都定義了begin與end函數,begin返回容器的第一個元素,end函數返回vector的末端元素的下一個,通常稱為超出末端迭代器,表明它指向了一個不存在的元素。如果vector為空,begin返回的迭代器與end返回的迭代器相同。end返回的迭代器實際上是一個“哨兵”。
注意區別:
vector<int>::const_iterator // an iterator that cannot write elements
const vector<int>::iterator // an iterator whose value cannot change
5,bitset類型
幾種bitset的構造函數:
bitset<n> b;
bitset<n> b(u); // u是一個usigned long弄的數字,將換算成二進制數
bitset<n> b(s); // b 是string對象s中含有位串的副本
bitset<n> b(s,pos,n); // b是s中從位置pos開始的n個位的副本
1,數組
沒有所有元素都是引用的數組,數組中定義的類型可以是內置數據類型或類類型或任意的復合類型(引用除外)。
數組的維數只能用在編譯階段就能知道的常量值。const int arSize=num; int ar[arSize];這樣是不行的,因為num變量在運行階段才會計算出。
如果沒有給數組顯式地初始化,則會像普通變量一樣進行初始化:1)在函數體外定義,則初始化為0;2)在函數體內定義,則其元素無初始化;3)不管數組在哪,如果其元素為類類型,則自動調用該類的默認構造函數。如果該類沒有默認的構造函數,則必須為數組的元素提供顯式的初始化。
vector對象不能用同類型的數直接進行初始化。假設有如下數組:const int ar_size=5; ar[ar_size]={0,1,2,3,4}>
vector<int> ivec(ar); // error
vector<int> ivec(ar,ar+ar_size); // ok
2,指針的引入
不允許把int型的0賦給指針,但是可以把const修飾的0可以賦於指針
cosnt int c_ival=0; int *p=c_ival;
C++提供了一種特殊類型的指針void*,void*只支持幾種有限的操作:1)與另一個指針進行比較;2)向函數傳遞void*指針或從函數返回void*指針;給另一個void*指針賦值。不允許使用void*指針操縱它所指向的對象。
ptrdiff_t是標准庫中定義的用於保存指向同一類型的指針之間減法的結果的類型。
const int* ptr; // ptr可以指向他變量,但是在沒有改變ptr之前,不能用ptr是改變它所指向的變量的值。
int* const ptr; // ptr不能指向其他變量,但是可以改變ptr所指向的變量的值。
注意:
typedef string *pstring;
const pstring cstr;
上面的cstr是一種const指針,指針指向字符串類型的變量。pstring const cstr是一樣的。
3,C風格字符串
每一個程序在執行時都占用一塊可用的內存空間,用於存放動態分配的對象,此內存空間稱為程序的自由存儲區或堆。
動態分配的數組不能像數組一樣使用初始化列表,只能初始化為元素類型的默認值。int* ar=new int[10]();後面的空括號可以讓數組元素都初始化為0。
用delete釋放自由存儲空間時,如果釋放的是數組,則別忘了[]。delete [] ar;
注意string對象的成員函數c_str()可以返回字符串的首指針。但是應該加const。 const char* str=s.c_str();
int* ip[4]:一個指向int的指針數組。
int (*ip)[4]:一個指針4元素數組的指針。
1,區別i++與++i
後置操作符需要先保存原來的值,再將i+1,然後返回原來的值;而前置操作符,只需要在原來值上加1,然後返回。所以++i比i++效率更高,當然如果i為int類型時,編譯器會對i++進行優化,但如果是其他類類型或指針時就不會了。
2,注意解除引用操作符與++操作符的優先級,在實際代碼中為了簡潔經常將*(i++)寫為*i++。因為++的優先級高於解除引用操作符。
3,在使用條件操作符時,盡量避免寫出深度嵌套的條件操作符。另外條件操作符的優先級非常低,在表示式中使用時要注意加括號,比如:cout<<(i<j?i:j);
4,關於sizeof運算符。sizeof的運算結果是編譯時的常量,注意下面的代碼的值:
5,在復合表達式求值時,要特別注意運算符的優先級與結合性。特別地,!=與==的優先級小於<=,>=等關系運算符。
6,在使用new進行動態內存分配時,有以下幾點值得注意:
1)動態創建的對象可以用括號進行初始化,比如:
2)可以delete刪除0指針,而且delete刪除的是分配到的內存區域,並沒有刪除指針變量p,p依然指向原來的地址,只是原來的內存已經不存在了。這時p稱為懸垂指針,應該將p設為0.
3)避免對同一內存空間使用兩次delete。、
1,在使用塊狀語句時注意,在塊狀語句內定義的變量作用域只在塊狀區域內。特別地,在控制語句,比如if或for語句中,初始化或定義的變量,都只有塊區域的作用域。
2,switch語句的使用。case標號必須是整形常量表達式,不允許在switch語句內定義變量如果在它下面還有case或default語句,因為這樣會在某些情況下,在沒有執行變量定義的case分支的情況下,執行變量定義下面case分支。除非把變量定義在代碼塊內。
3,在for循環中,如果有continue語句,會跳下continue後面的語句,但是不會跳變for語句中的計數器變化語句。
4,可以使用預處理器進行調試。
在編譯時加上參數就可以決定是否打印那些調試信息。
1,函數可以看作是程序員自己定義的操作符,與操作符一樣函數也可以進行重載。
2,下面是用輾轉相除法求最大公約數的函數,說明了函數定義的基本結構。
5,沒有返回值的函數(返回值為void)裡一般是不能有return語句,但是可以用return返回一個返回值為void的函數表達式。
6,函數允許提供默認的實參,在調用時,這一項參數可以省略,而讓程序使用默認值。一般應在函數聲明中指定默認實參,並將該聲明放在合適的頭文件中。
7,在函數體內定義的變量具有塊區域的作用域,可分為兩種一種為自動對象,如:形參。這類對象在每次函數調用時都會創建,在函數執行完時銷毀。還有一種對象為靜態局部對象,這種對象只有在程序結束時才會撤銷。不然一直在內存中保留。
8,對於那種經常需要調用且短小的函數,可以設置為內聯函數,這種函數在編譯時,編譯器會在函數調用處對函數進行展開,進行代碼替換。這樣就避免了函數調用中的開銷。定義內聯函數是在函數定義前加inline。一般需要將inline函數放在頭文件中。
9,在類的成員函數中有一類函數在後面加上const限定符,用來說明為常量成員函數,在對象使用時,只能讀取不能改變對象的數據成員。
10,不要把this指針寫在了成員函數的形參表中。
11,在定義類時,如果沒有定義默認的構造函數,那麼編譯器將為類創建一個合成的默認構造函數。這個函數將類的成員變量按對應變量類型初始化方法進行初始化:類類型的將調用該類的默認構造函數,內置類型則依賴於所處的環境是全局或靜態局部對象還是局部對象。合成的默認構造函數只適用僅包含類類型成員的類。
12,函數不能僅僅基於不同的返回類型而實現重載。
13,const在函數重載中值得注意的問題:
14,局部聲明的函數將會屏蔽將全局定義的重載函數。
15,指向函數的指針
函數指針指向函數而並非指向對象。bool (*pf) (int,int*); 其中pf是一個函數指針,該指針的類型為“指向返回bool類型並帶int與int*形參的函數的指針”。
1)可以用typedef來給指定函數的指針簡單定義:
上面代碼中定義了一種指針函數的類型,並用typedef提供了別名。f1與f2都是這種類型的指針。
2)給指向函數的指針初始化與賦值
對於定義好的函數,其函數名沒有被調用時,都被解釋為指向函數的指針,可以給同類型的指針賦值。
給指向函數的指針賦值為0,表明不指向任何函數。
在進行指向函數的指針賦值時,不存在任何類型的轉換。
3)通過指針調用函數
可以不用解除引用符號,如:f1(1,2)、(*f1)(1,2)。
4)指向函數的指針可以作為函數的形參:
上面兩個函數的聲明中上式第3個參數為一個指向函數指針類型,下式的第3個參數為一個函數類型,它會自動轉換為一個指針類型。
5)函數類型可以作為函數的形參,但是不能作為函數的返回類型。
6)在指向函數的指針指向重載函數時,類型必須一致。
1,標准庫類型不允許做復制和賦值操作。因為只有支持復制的元素類型可以存儲在vector中,所以流對象不能存儲在vector或容器中,另外函數的形參與返回類型也不能為流類型,如果需要則必須傳遞或返回指向該對象的引用或指針。一般來說,如果要傳遞IO對象以便對它進行讀 寫,可以用非const引用方式傳遞這個流對象。對IO對象的讀寫會改變它的狀態,所以必須是非const的。
2,每個IO對象都管理著一個緩沖區,有以下幾種方式可以刷新緩沖區(將緩沖區內容寫到設備上)。
1)輸出緩沖區的刷新:flush刷新流但不添加任何字符;ends這個操作符在緩沖區中插入空字符NULL,然後刷新它。endl換行並刷新。
2)unitbuf操作符:cout<<unitbuf<<”first”<<”second”<<nounitbuf;nounitbuf操作符將流恢復為正常的,由系統管理的緩沖區刷新方式。
3)程序崩潰時,不會刷新緩沖區。這一點在調試已崩潰的程序時需要特別注意。
4)可以用tie函數將istream與ostream捆綁在一起,當使用任何IO操作時都會刷會實參所關聯的緩沖區。
3,注意清除文件流的狀態,下面程序從一個vector中讀文件的名字,並對每個文件內的內容進行處理,如果開始的流是定義在循環外的,則需要在循環結束時清除文件流的狀態。
上面程序中,每一次讀文件,都會以遇到文件結束符或其他錯誤終止,這個點上input處於錯誤狀態。如果關閉該流前沒有調用clear消除流的狀態,接著在input上做的任何輸入運算都會失敗。
4,stringstream由iostream派生而來,提供讀寫string的功能。可以將一個字符串轉化為流用於輸入或輸出。這個類主要有兩種常見的用處:
1)將一定格式的變量值組成一個字符串。 假設在一個循環內,我們要保存中間數據到硬盤,那麼需要文件名,且需要將循環的索引寫入文件名,避免文件名的重復。
2)將一串有格式的字符串,按格式解析為一些基本類型數據。比如,需要將一行日志文件內容中的字符串與整數分別提取出來: