c++Primer筆記

來源:互聯網
上載者:User

筆記比較亂,得從下往上看,呵呵

 

開啟一個僅用於輸出檔案:ofstream outfile("copy.out",ios_base::out);//檔案名稱,開啟模式
ios_base::out 輸出模式  ios_base::app 附加模式,輸出模式開啟已經存在的檔案,則檔案中的數

據將被丟棄,如果附加模式開啟,新資料將添加在檔案尾部,兩種模式中,如果檔案不存在,程式會建立

一個新檔案.
開啟一個作為輸入的檔案:ifstream inFile("filename")
   outFile.puc(ch);     inFile.get(ch)
我們既可以用C風格字元數組的形式讀入字串,也可以以string類類型的形式讀入字串.string的

好處是與字串相關的記憶體可被自動管理.

while( cin>> ival) 從標準輸入讀入一個序列,知道cin為false為止,有兩種情況會使一個istream

對象被計算為false:讀到檔案結束(在這種情況下,我們已經正確的讀完檔案中所有的值)或遇到一個

無效的值,比如3.1515926
預設情況下,所有空白符會丟掉,如果希望讀入空白符,或許是為了保留原始的輸入格式,或者是為了

處理空白符,一種方法是使用istream的get()(ostream對應put);

預設情況下,false文字值被輸入為0,而true被輸出為1

max( int val1, int val2) { cout<<(val1 >val2)? val1:val2; }
則max(10,20)則輸出0,因為<<的優先順序高於?的有限級
正確的應為:{ cout<<((val1 >val2)? val1:val2); }

在程式中使用iostream庫,必須包含相關的標頭檔,如#include <iostream>
輸入輸出操作是有istream(輸入資料流)和ostream(輸出資料流)類提供的,iostream是同時從istream和

ostream派生,允許雙向輸入/輸出.為了方便,這個庫定義了三個標準流對象:

(使用者終端的讀寫操作)
cin:代表標準輸入的istrem對象,使我們能夠從使用者終端讀入資料
cout:代表標準輸出的ostream對象,cout能使我們能夠向使用者終端寫資料.
cerr.

對檔案的讀寫操作:include <fstream>
ifstream:從istream派生,把一個檔案綁到程式上用來輸入.
ofstream:從ostream派生,把一個檔案綁到程式上用來輸出.
fstream:從iostream派生,把一個檔案綁到程式上用來輸入和輸出.
由於fstream標頭檔中也包含了iostream標頭檔,所以我們不需要同時包含這兩個檔案

/*FILE *fp,*outf;
int ch;
while((ch=fgetc(fp))!=EOF)
{
cal[ch]++;
in_num++;
}
fclose(fp);*/
=====================================================================================
   重載的操作符在類體中被聲明,聲明方式同普通函數一樣,只不過他的名字包含關鍵字operator,

以及緊隨其後的一個預定義操作符.

類的初始化有一種可替換的方式:成員初始化表,是由逗號分開的成員名極其初值的列表.成員初始化

表只能在建構函式定義中被制定,而不是在其聲明中,該初始化表被放在參數表和建構函式體之間,由

冒號開始.

如果一個類聲明了一個包含多個參數的建構函式,但沒有聲明預設建構函式,則每個類對象的定義都

必須提供所需的實參.在實踐中,如果定義了其他的建構函式,則也有必要提供一個預設建構函式.

嵌套類:除非外圍類被聲明為嵌套類的友元,否則他沒有權利訪問嵌套類的私人成員.嵌套類也沒有任

何特權訪問外圍類的私人成員,如果要授權,也必須把它聲明為嵌套類的友元.

位域(bit-field):它可以被聲明存放特定數目的位,位域必須是有序資料類型,位於標識符後面跟一

個冒號,然後一個敞亮運算式制定位元.如:
typedef unsigned int Bit;
class File
{
public:
  Bit a:7;
  Bit b:8;
  Bit c:6;
}

聯合是一種特殊的類,一個聯合中的資料成員在記憶體中的儲存是互相重疊的,每個資料成員都在相同

的記憶體位址開始.分配給聯合的儲存區數量是"要包含它最大的資料成員"所需的記憶體數.

靜態成員函數訪問待用資料成員

s2為某類對象的指標 運算式 s2->height() 可以寫成 (*s2).height() 結果完全相同   

    一個友員或許是一個名字空間函數,另一個前面定義的類的一個成員函數,也可能是一個完整的

類.在使一個類成為友員時,友員類的所有成員函數都被給予訪問"授權友誼類的非公有成員"的權利.

資訊隱藏:
公有成員(public):在程式的任何地方都可以被訪問.
私人成員(private):只能被成員函數和類的[友元]訪問
保護成員(protected):對衍生類別就像public一樣,對其他程式則表現的像private.
預設的是private

除了待用資料成員外,資料成員不能在類體中被顯式的初始化,如:class firts{ int meni=0;}
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
c++語言要求綁定在const vector上的iterator也必須是const iterator
const vector<int> vec; vector<type>::const_iterator iter=vec.begin();

拋出異常:在C++中,異常常常用類class來實現. 如class popOnEmpty();
throw popOnEmpty();//拋出異常是一個建構函式運算式
try 塊必須包圍能夠拋出異常的語句,try塊以關鍵字try開始,後面是花括弧括起來的語句序列,在

try塊之後是一組處理代碼,被稱為catch語句.
try{ ... } catch(pushOnFull){ ... }
           catch(popOnEmpty){ ... }
如果catch子句不包含返回語句,catch子句完成它的工作後,程式的執行將在CATCH子句列表的最後子

句之後繼續進行.C++的異常處理機制是不可恢複的,一旦異常被處理,程式的執行就不能夠在異常被

拋出的地方繼續.
-------------------------------------------------------------------------
422 int min(int (&r_array)[size]) { ... }
300
在C++中,數組永遠不會按值傳遞,它是傳遞第一個元素的指標.數組的長度不是參數類型的一部分,函

數不知道傳遞給它的數組的實際長度,一種常見的機制是提供一個含有數組長度的額外參數.

另外一種機制是將參數聲明為[數組的引用],當參數為一個數群組類型的引用時,數組長度成為參數和

實參類型的一部分,編譯器檢查數組實參的長度與在函數參數類型中指定的長度是否匹配.
例如:void putValue( int (&arr)[10] )

參數可以是多維陣列,這樣的參數必須指明第一維以外的所有維的長度
例如:void putvalue( int matrix[][10],int rowsize)
int (*matrix)[10];//一個二維數組,每行由10個列元素構成
int *matrix[10]   //一個含有10個指向int的指標的數組
[]的優先順序高於*
-------------------------------------------------------------------------
如果兩個函數的傳回型別和參數表精確匹配,則第二個生命為第一個的重複聲明.
函數的傳回型別不足以區分兩個重載函數.

空類大小為1;

標準C++庫中的所有組建都是在一個被稱為std的名字空間中聲明和定義的.在標準標頭檔(如

<vector>或<iostream>)中聲明的函數,對象和類模板,都被聲明在名字空間std中.名字空間std的成

員不能不加限定修飾訪問,最簡單的解決方案是在#include指示符後面加上using指示符如下:
using namespace std;

常量對象的動態分配:const int *pci=new const int(1024);//必須初始化,前後必須都有const

C風格字串 char *str="123456789"長度為9,實際佔用空間為10,都以Null 字元結尾,所以要複製的時

候要多申請一個位元組的空間,sizeof=10 ;strlen=9;
char *str2= new char[strlen(str)+1];否則會發生記憶體錯誤
strcpy(str2,str);

申請動態二維數組:
int **pi=new int*[m];
for(int i=0; i<m; i++)
pi[i]=new int[n];

for(i=0; i<m; i++)
delete [] pi[i];
delete [] pi;

三個指標常見錯誤:
 1.應用delete運算式失敗,使記憶體無法返回空閑儲存區,稱為記憶體流失.(memory leak)
 2.對同一記憶體應用了兩次delete運算式.通常發生在兩個指標指向同一個動態指派至的時候.通過

某個指標釋放對象,該對象的記憶體返回給空閑儲存區,然後又被分配給某個別的對象,接著指向舊對象

的第二個指標被釋放,新對象也就跟著消失了.
 3.delete後,指標沒設定為0;

if(pi != 0) delete pi;  //沒必要,如果指標運算元被設定為0,則C++會保證delete運算式不會調

用操作符delete(),所以沒必要測試其是否為0.
空閑指標是程式錯誤的一個根源,很難被檢測到,一個較好的方法是在指標指向的對象被釋放後,將該

指標設定為0,這樣可以清楚的表明該指標不再指向任何對象.
    delete運算式只能應用在指向的記憶體是用new運算式從[空閑儲存區[分配的指標上, 將delete表

達式應用在指向空閑儲存區以外的記憶體的指標上,會使程式運行期間出現未定義的行為.
如:int i=8; int *pi=&i;  delete pi;//不安全,pi指向i,是一個局部對象,運行會發生記憶體錯誤
    int *pi2=new int(9); delete pi2;//安全

動態分配的對象被分配在程式的[空閑儲存區的記憶體池]中.空閑儲存區的一個特點是,氣宗分配的對

象沒有名字,new運算式沒有返回實際分配的對象,而是返回指向該對象的指標,對該對象的全部操作

都要通過這個指標間接完成.第二個特點是分配的記憶體是未初始化的,空閑儲存區的記憶體包含隨機的

位元模式,它是程式運行前該記憶體上次使用留下的結果.
因為空白閑儲存區是有限的資源,所以當我們不再需要已指派的記憶體時,就應該馬上將其返還給該空閑

儲存區,這是很重要的.

在局部域中的變數聲明中引入了局部對象,有三種局部對象:自動對象(automatic object),寄存器對

象(register object),局部靜態對象(local static object)
    自動對象的儲存分配發生在定義它的函數被調用時,分配給自動變數的儲存區來自於[程式的運

行棧],它是函數的活動記錄的一部分.未初始化的自動對象包含一個隨機的位元模式,是該儲存區上次

被使用的結果,它的值是為指定的.函數結束時,它的活動記錄被從運行棧中彈出,與該自動對象關聯

的儲存區被真正的釋放.
    在函數中頻繁被使用的自動變數可以用regester聲明.如果可能的話,編譯器會把該對象裝載到

機器的寄存器中,如果不能夠的話,則該對象仍位於記憶體中.
for( register int ix=0; ix<sz; ++ix);
   把局部對象聲明為static,把對象在整個程式運行期間一直存在的局部對象,當一個局部變數的值

必須在多個函數調用之間保持有效時,我們不能使用普通的自動對象,自動對象的值在函數結束時被

丟棄,可以聲明為static,靜態局部變數對象被程式自動初始化為0; 
void fuc() { static int depth; }

extern為聲明但不定義一個對象提供了一種方法,該方法承諾了該對象在其他地方被定義:或者在此

文字檔的其他地方,或者在程式的其它文字檔中,例如 extern int i;關鍵字extern也可以 在函

數聲明中指定.

名字解析期間尋找域的順序由內向外,所以在外圍域中聲明被嵌套域中的同名聲明所隱藏.

用來區分名字含義的一般上下文就是域(scope),C++支援三種形式的域:局部域(local scope),名字

空間域(namespace scope),類域(class scope).
名字解析是把運算式中的一個名字與某一個聲明想關聯的過程.

函數參數的類型不能是函數類型,函數類型的參數將被自動轉換為該函數類型的指標.

int sort(string*, string*, int (*)(const string &, const string &));
等價與 typedef int (*PFI2S)(const string &, const string &);
       int sort(string*, string*, PFI2S);

        int(*testCases[10]) ();//函數指標數組
等價於: tepedef int(*PFV)();
        PFV testCases[10];

函數指標初始化和賦值: int lexicoCompare(const string &s1, const string &s2) { ... }
函數名lexicoCompare被解釋成 int (*)(const string &, const string &)的指標,將取址操作符

作用在函數名上也能產生指向該函數類型的指標,因此lexicoCompare AND &lexicoCompare類型相同

,指向函數的指標可以如下初始化:
   int (*pfi)  (const string &, const string &) = lexicoCompare;
OR int (*pfi2) (const string &, const string &) = &lexicoCompare;
只有當複製操作符左邊指標的參數表和傳回型別與右邊函數或指標的參數表和傳回型別完全符合時,

初始化和賦值才是正確的.
應用函數指標時,用 pf(ia,size) OR (*pf)(ia,size) 而不能用 *pf(ia,size);

函數指標:函數名不是其類型的一部分,函數的類型只由它的傳回值和參數表決定.
int  *pf  (const string &, const string &); NO
int (*pf) (const string &, const string &); YES

實際上,命令列選項是main()實參
int mian(int argc, char *argv[]) { ... }
argc:命令列選項的個數,argv包含argc個C風格字串,代表了由空格分割的命令選項.argv[0]總是

被設定為當前正被調用的命令,從索引1到argc-1表示被傳遞給命令的實際選項.

*************************************************************************
調用函數有一個嚴重的缺點:調用函數比直接計算要慢的多,不但必須拷貝實參,儲存機器的寄存器,

程式還必須轉向一個新位置.內嵌函式(inline)函數給出了一個解決方案.它將在程式中的每個調用

點上被"內聯地"展開. 一個遞迴函式不能在調用點完全展開(雖然第一個調用可以),一個大的函數也

不太可能在調用點展開,一般的,inline機制用來最佳化小的,只有幾行的,經常被調用的函數.

為了替換一個大型的參數表,程式員可以將參數聲明為類(或結構體),數組或某一容器類型,這樣的參

數可以用來包含一組參數值.類似的情況,一個函數只能返回一個值,如果程式要求返回多個值,那麼

程式員可以將某些函數參數聲明為引用,這樣,函數可以直接修改實參,或者可以聲明一個函數,它的

傳回型別是一個可以包含一組傳回值的類或某一種容器類型.

一個程式中各種函數通過兩種機制進行通訊,一種方法是使用全域對象,另一種方法是使用函數參數

表和傳回值.

預設情況下,函數的傳回值是按值傳遞的.局部對象的生命期隨函數的結束而結束,在函數結束後,該

引用變成未定義的記憶體的別名.在這種情況下,傳回型別應該被聲明為非參考型別,然後在局部對象的

生命週期結束之前拷貝局部變數.
函數返回一個左值,對傳回值的任何修改都將改變被返回的實際對象

省略符號參數:當我們無法列出傳遞給函數的所有實參的類型和數目,這時我們可以使用省略符號(...)指

定函數參數表.省略符號掛起類型檢查機制,它的出現告知編譯器,當函數被調用時,可以有0個或多個實

參,而實參的類型位置,兩種形式:void foo(para_list,...)  void foo(...);
for example: int printf( const char* ...)

預設實參:函式宣告可以全部或部分參數制定預設實參,在左邊參數的任何預設實參被提供之前,最右

邊未初始化參數必須被提供預設實參.這是由於函數調用的實參是按照位置來解析的.
         int ff(int a, int b, int c=0)
重新聲明:int ff(int a, int b=0, int c)

指標,引用的區別:引用必須初始化為指向一個對象,一旦初始化了,它就不能再指向其它對象,而指標

可以指向一系列不同的對象也可以什麼也不指向.引用參數的一個重要用法是,它允許我們有效實

現操作符重載的同時,還能保證用法的直觀性.
    因為指標可以指向一個對象或者沒有任何對象,所以函數在確定指標實際指向一個有效對象之

前不能安全的解引用(dereference)一個指標.所以在使用指標作為參數時,我們必須首先判斷指標是

否為空白 ptr == 0 OR ptr == NULL

如果要修改指標本身,而不是指標引用的對象,那麼可以聲明一個參數,該參數是一個指標引用
如:void ptrswap(int *&v1, int *&v2){}

函數要想操作實參,就用指標傳遞或者引用傳遞,不能用值傳遞

for迴圈內部定義的對象的可視性局限在for迴圈體內,外部存取非法,WHILE迴圈也一樣

在if(condition)中condition中定義的對象,旨在與if相關的語句或語句塊兒中可見.試圖在if語句

後面訪問會導致編譯錯誤.

字元在進行算數運算是取其ASC碼,如 'a'為97; 3+'a'=100

C++在運算前自動進行算數轉換,以便在計算前轉換成相同的類型,轉換規則是小類型總是被提升為大

類型,以防精度損失.

&:按位與  &&:邏輯與;  >>移位操作必須有左值,否則會返回去,例如 a>>3;A右移了3位,輸出A時還

是原值,要實現移動效果 A= A>>3;也可以實現整數位移,如 5<<8;//5左移8位

逗號運算式是一系列由逗號分開的運算式,這些運算式從左向右計算,結果是最右邊運算式的值

系統為每個程式提供了一個在程式執行時可用的記憶體池.這個可用的記憶體池被稱為程式的 空閑儲存

區 或 堆.運行時刻的記憶體配置被稱為動態記憶體分配.

SIZEOF()一個對象或者類型名的位元組長度,應用在數組上時,返回整個數組的位元組長度

數群組識別碼代表數組中第一個元素的地址,*IA相當於IA[0],*(IA+1)相當於IA[1]

字串(常量)包含一個額外的終止Null 字元

非CONST變數不能被用來指定數組的維數

如果有必要,算術值和指標值也能隱式的轉換成BOOL類型的值,0或null 指標被轉換成FALSE,所有的其它

值都被轉換成TRUE;

引用主要被用作函數的形式參數,通常將類對象傳遞給一個參數.

const對象的地址只能賦值給const對象的指標,但是指向const對象的指標可以被賦以一個非const對

象的地址,而且該非const對象不能通過const指標改變.

INT *P=0; null 指標

字串被儲存在一個字元數組中,一般通過一個 CHAR* 類型的指標來操縱它

任何人如果事先不知道指標是否有值,都應該先行測試,然後才對指標進行操作

如果我們要做的僅僅是持有地址值(可能把一個地址同令一個地址比較),那麼指標的實際類型就不重

要了.C++提供了一種特殊的指標來支援這種需求:空類型指標(VOID*),它可以被任何資料指標類型的

地址值賦值.不能操作空類型指標所指向的對象.

指標:為清楚起見,最好寫成  int *x  而不是  int*  x;
int * x,y;X是指標,而Y則不是

右值:被讀取的值 左值:位置值

字元文字前加L表示寬字元文字,如L'a',寬字元常量用來支援某些語言的字元集合,如漢語

整數文字常量可以被寫成十進位,八進位,十六進位,但這不會改變整數值的位序列.
string類型支援通過下標操作符訪問單個字元

判斷字串是否結束: *str++;不結束為TRUE,結束時為FALSE
WHILE( *STR++) COUT<<*STR;   最後STR指標指向該字串的後一個地址,要正確使用需要返回!(參

考STRCPY)
指標為空白,則str=0

20 023,0X14,在整形文字常量後加L,將其指定為LONG整形.加U將其指定為一個無符號數

迭代器是一個支援指標類型抽象的類對象

  一般來說,當兩個或多個函數重複相同的代碼時,就會將這部分代碼抽取出來,形成獨立的函數,以

便共用,以後,如果需要改變這些實現,則只需改變一次.

    函數調用比直接存取記憶體的開銷要大的多;內嵌函式在他的調用點上被展開,類定義中被定義的

函數會被自動當作是內斂函數

int *pint=new int(12);//分配指標指向一個整形,賦初值為12  delete pint;
int *pia= new int[4]; //分配一個4個整數元素的數組        delete [] pia;

C++中,指標的主要作用是管理和操作動態分配的記憶體

防止一個標頭檔被多次包含:
#ifndef BOOKSTORE_H
#define BOOKSTORE_H

Bookstore.h內容

#endif

程式中用 #ifdef  #endif來判斷一個前置處理器變數是否已被定義
------------------------------------------------------------------
檔案輸入輸出:#include <fstream>
ofstream outfile("out_file")
ifstream infile("in_file")
infile>>a;
outfile<<a;

數組之間不能直接複製 如 A=B,數組不知道自己的長度

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.