學習筆記:C++基礎概念總結


These my learning notes about the C++ language

1、變量有哪幾種類型?

  1. auto 存儲類型:采用棧堆方式分配內存空間,屬於一時性存儲,其存儲空間可以被若干變量多次覆蓋使用。
  2. register存儲類型:存放在通用寄存器中
  3. externa存儲類型:所用函數和程序段中都可以引用
  4. static存儲類型:在內存中是以固定地址存放的,在整個程序運行期間都有效。

2、什么是內聯函數,它有那些特點?

定義時使用關鍵字 inline 的函數叫內聯函數,編譯器在編譯時在調用處用函數體進行替換,節省了參數傳遞,控制轉移等開銷,內聯函數體內不能有循環語句和 switch 語句,內聯函數的定義必須出現在內聯函數第一次調用之前,對內聯函數不能進行異常接口聲明。

3、調用重載函數時,通過什么來區分被調用的是哪個函數?

重載函數的函數名是相同的,但它們的參數的個數和類型不同,編譯器根據實參和形參的類型和個數的最佳匹配,自動確定調用那一個函數。

4、公有類型成員和私有類型成員有什么區別?

公有類型成員用public關鍵字聲明,共有類型定義了類的外部接口;私有類型的成員用private關鍵字聲明,只允許本類的函數成員來訪問,而類外部的任何訪問都是非法的,這樣,私有成員就整個隱蔽在類中,在類的外部根本就無法被看到,實現了訪問權限的有效控制。
數據成員和成員函數都可以為公有的或私有的,但數據成員最好是聲明為私有的。

5、protected關鍵字有何作用?

protected用來聲明保護類型的成員,保護類型的性質和私有類型的性質相似,其差別在於繼承和派生時派生類的成員函數可以訪問基類的保護成員。

6、構造函數和析構函數用什么作用?

構造函數的作用就是在對象被創建時利用特定的值構造對象,講對象初始化一個特定的狀態,使此對象具有區別於彼對象的特征,完成的就是一個從一般到具體的過程,構造函數在對象創建的時候由系統自動調用。
析構函數與構造函數的作用幾乎正好相反,它是用來完成對象被撤出前的一些清理工作,一般情況下,析構函數是在對象的生存周期即將結束的時刻由系統自動調用,它的調用完成之后,對象也就消失了,相應的內存空間也被釋放。

7、什么是拷貝構造函數?

拷貝構造函數是一種特殊的構造函數,其形參是本類的對象的引用,其作用是使用一個已經存在的對象,去初始化一個新的同類的對象。在以下三種情況下會被調用:
當用類的一個對象去初始化該類的另一個對象時;
如果函數的形參是類對象,調用函數進行形參和實參結合時;
如果函數的返回值是類對象,函數調用完成返回時。

8、靜態數據成員和普通數據成員的區別?

普通數據成員屬於類的一個具體的對象,只有對象被創建了,普通數據成員才會被分配內存。而靜態數據成員屬於整個類,即使沒有任何對象創建,類的靜態數據成員變量也存在。因為類的靜態數據成員的存在不依賴與於任何類對象的存在,類的靜態數據成員應該在代碼中被顯示的初始化,一定要在類外進行。外部訪問類的靜態成員只能通過類名來訪問。類的靜態成員函數無法直接訪問普通數據成員(可以通過對象名間接的訪問),而類的任何成員函數都可以訪問類的靜態數據成員。靜態成員和類的普通成員一樣,也具有public、protected、private三種訪問級別,也可以具有返回值、const修飾符等參數。

9、關於靜態成員函數

靜態成員函數的地址可用普通函數指針儲存,而普通成員函數地址需要用 類成員函數指針來儲存。靜態成員函數不可以調用類的非靜態成員。因為靜態成員函數不含this指針。靜態成員函數不可以同時聲明為 virtual、const、volatile函數。

10、友元函數和友元類

友元是不同的類之間、類與類外的函數之間的共享數據的機制。使用friend關鍵字聲明,友元函數可以訪問相應類的保護成員和私有成員。友元類它的所有成員函數都是相應類的友元函數。友元關系不具有交換性、傳遞性,也不能被繼承。

11、運算符“*”和運算符“&”的作用是什么?

* 稱為指針運算符,是一個一元運算符,表示指針所指向的對象的值;& 稱為取地址運算符,也是一個一元操作符,是用來得到一個對象的地址。
個人認為它們是一對作用相反的運算符。

12、引用和指針

引用是給另外一個變量起別名,所以引用不會分配內存空間。聲明方法:(類型標識符 &引用名=目標變量名;(如int &r = num;))。指針是一個存放地址的變量,需要分配內存空間,聲明方法:(類型標識符 *指針名 = 目標變量地址(int * p = &a;))。對於聲明后的指針,p指向的是變量a的地址,*p 表示的是變量a的內容。在C++中使用引用代替指針可以提高程序的安全性,但當需要對變量重新賦值以另外的地址或賦值為NULL時只能使用指針。

13、const int * p1 和 int * const p2 的區別

const int * p1 聲明了一個指向整型常量的指針p1,因此不能通過指針p1來改變它所指向的整型值;int * const p2 聲明了一個指針型常量,用於存放整型變量的地址,這個指針一旦初始化后,就不能被重新賦值。
(理解方法:主要是參考const修飾的誰)。

14、空指針和野指針

空指針:一般聲明一個指針變量賦值為NULL,這就是空指針,各個類型的空指針都存在確確實實的內存地址,但是不會指向任何有效的值的內存地址,對空指針操作,例如訪問屬性和方法,會拋出空指針異常,因為空指針指向的內存地址沒有對應的物理地址。
野指針:指那些釋放內存,但是指針賦值為空,這時候的指針指向任意地址,好可怕,例如指向內核地址或不屬於本程序的內存地址,程序會被kill,即奔潰。
內存泄漏:分為堆泄露和資源泄露 兩種,內存分配失敗或者內存分配成功卻沒有指針指向它(即無法操作該內存),會導致內存分配的越來越多,導致系統內存不夠而終止程序。

15、C/C++ 內存管理需要遵循的規則

malloc 或者 new 申請內存之后,應該立即檢查指針值是否為 NULL ,防止使用指針值為NULL的內存;
不要忘記數組和動態內存賦初值,防止未被初始化的內存作為右值使用;
避免數組或者指針下標越界,特別要當心“多1”或者“少1”的操作;
動態內存的申請與釋放必須配對,防止內存泄露;
free或者delete釋放了內存之后,立即將指針設置為NULL,防止產生“野指針”;

16、關於繼承與派生

首先要明確從基類繼承的成員的訪問控制屬性受兩方面因數的影響(1、成員在基類中原來聲明的訪問控制屬性;2、繼承方式)。在運用經常關系時,要注意基類的構造函數和析構函數都不能繼承,但是在建立派生類對象時基類的構造函數會被自動調用,派生類消亡時,會自動調用基類的析構函數。在多繼承的情況下,如果存在公共基類,就會出現成員標識二義性的問題,這是將公共基類作為虛基類繼承是一個比較好的解決方案(虛基類繼承的語法格式:class 派生類名:virtual 繼承方式 基類名)。

17、關於多態性

多態是指同樣的消息被不同類型的對象接收時導致完全不同的行為,是對類的特定成員函數的再抽象。C++支持的多態有多種類型,重載(包括函數重載和運算符重載)和虛函數是其中主要的方式。

18、關於抽象類

帶有純虛函數的類是抽象類,抽象類的主要作用是通過它為一個類族建立一個公共的接口,使它們能夠有效的發揮多態特性。抽象類聲明了一組派生類共同操作接口的通用語義,而接口的完整實現,即純虛函數的函數體,要由派生類自己給出。但抽象類的派生類並非一定要給出純虛函數的實現,如果派生類沒有給出純虛函數的實現,這個派生累仍然是一個抽象類。

19、虛構造函數和虛析構函數

在C++中,不能聲明虛構造函數,多態是不同的對象對同一消息有不同的行為特性,虛函數作為運行過程中多態的基礎,主要針對對象的,而構造函數是在對象產生之前運行的,因此虛構造函數是沒有意義的。可以虛析構函數,析構函數的功能是在該類對象消亡之前進行一些必要的清理工作,如果一個類的析構函數是虛函數,那么由它派生而來的所有子類的析構函數也是虛函數,析構函數設置為虛函數之后,在使用指針引用時可以動態連編,實現運行時的多態,保證使用基類的指針就能夠調用適當的析構函數針對不同的對象進行清理工作。

20、STL的容器、迭代器和算法概念

STL的容器庫包括7種基本容器:向量(vector)、雙向隊列(deque)、列表(list)、集合(set)、多重集合(multiset)、映射(map)和多重映射(multimap)。這7種容器可以分為兩種基本類型:順序容器好關聯容器。
STL根據迭代器的功能,將它們分為5類:輸入迭代器、輸出迭代器、前向迭代器、雙向迭代器、隨機訪問迭代器。
STL標准模板庫中的算法大致分為4類:非可變序列的算法(不會改變容器的內容)、可變序列的算法、排序相關的算法、通用數值算法。

21、流類庫與輸入/輸出

I/O 流類庫是一個提供輸入/輸出功能的、面向對象的類庫。
流是對輸入/輸出的一個抽象表述、程序通過從流中提取字符和向流中插入字符來實現輸入輸出。一般來說、流是與實際字符源或目標相關的,例如磁盤文件、鍵盤或顯示器,所以對流進行的提取或插入操作實際上就是對物理設備的操作。
標准輸入/輸出流對象時連接程序與標准輸入/輸出設備的,常用的標准輸入流有cin,標准輸出流有:cout、cerr、clog。標准流對象都是在<iostream>中預先聲明好的。

22、異常處理

當一個函數在執行的過程中出現了一些不平常的情況,或運行結果無法定義的情況,使得操作不得不被中斷時,這就是所謂的異常。異常通常是用throw關鍵字產生的一個對象,用來表明出現了一些意外的情況。C++的異常處理機制有很多優點,可以使的異常的引發和處理不必在一個函數中,這樣底層的函數可以着重解決具體問題,而不必過多的考慮異常的處理。上層調用者可以在適當的位置設計對不同類型異常的處理。C++提供了三個關鍵字來對異常進行處理:
try:可能拋出異常的程序段必須以try開。緊跟着try的是一段包含在大括號中的程序,這段程序有可能拋出異常。
throw:異常要通過關鍵字throw來拋出。異常對象的類型決定那一個catch語句可以捕獲這一異常。
catch:處理異常的程序必須以catch開始。跟隨在catch后面的是一段包含在大括號中的程序。

23、C/C++宏定義

#define是C語言提供的宏定義命令,其主要目的是使程序編寫規范,修改調試容易,並在一定程度上提高程序的運行效率。使用#define命令將一個標識符定義為一個字符串,該標識符被稱為宏名,被定義的字符串稱為替換文本。該命令有兩種格式:一種是簡單的宏定義,另一種是帶參數的宏定義。

24、lambda函數

C++中lambda函數是作為C++11新特新添加到C++中的,其主要是以匿名函數捕獲scope內變量的方式構造閉包(closure)。相關標准參考:c++ reference


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM