C++ 要注意地方

可以自行ctrl + F 尋找相關內容

 

  1. 重載運算符:
    1. - unary operators should be members    單目運算符應該爲成員函數
      - = () [] -> ->* must be members          這些運算符必須爲成員函數重載
      - assignment operators should be members  賦值應該爲成員函數
      - all other binary operators as non-members 其他雙目運算符沒有太大要求。
    2. (1)運算符的左右操作數不同,須用友員函數重載;

      (2)當運算符的操作需要修改類對象狀態時,應用成員函數重載。

      (3)友員函數不能重載運算符 = () [] ->

      必須要用友員函數重載的運算符 >> << 

  2. 類的初始化和構造函數初始化。

    1. 類初始化變量是按照變量聲明的順序來初始化的,不是按照構造函數的先後順序來初始化的

    2. 構造函數初始化時必須採用初始化列表一共有三種情況,
      1.需要初始化的數據成員是對象(繼承時調用基類構造函數)
      2.需要初始化const修飾的類成員
      3.需要初始化引用成員數據

    3. 建立派生類對象時,3 種構造函數分別是 a(基類的構造函數)、b(成員對象的構造函數)、c(派生類的構造函數)這 3 種構造函數的調用順序爲 abc 析構時順序相反(想象一下棧)

                             

 

 

 

3. C++ io

參數裏的表達式從右往左計算,因爲按照c語言的調用約定,壓棧時先壓最右邊的參數

 

 

4.

空類求sizeof爲1,加不加構造函數對sizeof沒影響,但有了虛函數,則需要有一個指針指向虛函數表,32位下,指針sizeof爲4

 

5.

r 打開只讀文件,該文件必須存在。

r+ 打開可讀寫的文件,該文件必須存在。

rb+ 讀寫打開一個二進制文件,只允許讀寫數據。

rt+ 讀寫打開一個文本文件,允許讀和寫。

w 打開只寫文件,若文件存在則文件長度清爲0,即該文件內容會消失。若文件不存在則建立該文件。

w+ 打開可讀寫文件,若文件存在則文件長度清爲零,即該文件內容會消失。若文件不存在則建立該文件。

a 以附加的方式打開只寫文件。若文件不存在,則會建立該文件,如果文件存在,寫入的數據會被加到文件尾,即文件原先的內容會被保留。(EOF符保留)

a+ 以附加方式打開可讀寫的文件。若文件不存在,則會建立該文件,如果文件存在,寫入的數據會被加到文件尾後,即文件原先的內容會被保留。 (原來的EOF符不保留)

wb 只寫打開或新建一個二進制文件;只允許寫數據。

wb+ 讀寫打開或建立一個二進制文件,允許讀和寫。

wt+ 讀寫打開或着建立一個文本文件;允許讀寫。

at+ 讀寫打開一個文本文件,允許讀或在文本末追加數據。

ab+ 讀寫打開一個二進制文件,允許讀或在文件末追加數據

 

6.

算法的特性:輸入輸出、有窮性、確定性、可執行性

一個算法應該具有以下五個重要的特徵:   1、有窮性: 一個算法必須保證執行有限步之後結束;   2、確切性: 算法的每一步驟必須有確切的定義;   3、輸入:一個算法有0個或多個輸入,以刻畫運算對象的初始情況,所謂0個輸入是指算法本身定除了初始條件;   4、輸出:一個算法有一個或多個輸出,以反映對輸入數據加工後的結果。沒有輸出的算法是毫無意義的;   5、可行性: 算法原則上能夠精確地運行,而且人們用筆和紙做有限次運算後即可完成

設計需要:正確性、底耦合高效率低存儲、可讀性、健壯性

7.

數據結構:指的是數據之間的相互關係,包含三個內容:邏輯結構,存儲結構和數據的運算

數據的邏輯結構指數據元素之間的邏輯關係,分兩種,線性結構和非線性結構。

常用的線性結構有:線性表,棧,隊列,雙隊列,數組,串。

數據結構在計算機中的表示(又稱映像)稱爲數據的物理結構,或稱存儲結構。
數據的存儲結構可採用順序存儲或鏈式存儲的方法。

存儲結構是數據的邏輯結構用計算機語言的實現,常見的存儲結構有 順序存儲,鏈式存儲,索引存儲,以及散列存儲。其中散列所形成的存儲結構叫散列表(又叫哈希表),因此哈希表也是一種存儲結構。

棧只是一種抽象數據類型,是一種邏輯結構,棧邏輯結構對應的順序存儲結構爲 順序棧,對應的鏈式存儲結構爲鏈棧。循環隊列是隊列的順序存儲結構,鏈表是線性表的鏈式存儲結構。

 

8.

C++的虛函數必須是類的一個成員,而不允許是類的友元

 

9.

C++規定=,[ ],(),->這四個運算符只能被重載爲類的非靜態成員函數,其他的可以被友元重載,主要是因爲其他的運算符重載函數都會根據參數類型或數目進行精確匹配,這四個不具有這種檢查的功能,用友元定義就會出錯。

 

10.

在C語言中,沒有專門的邏輯型數據類型,而是用0和1來表示邏輯值;因此只有 整型、實型、字符型

C++中的基本數據類型爲() 此時答案爲整形,字符型,浮點型,布爾型。

 

11.

%要求兩邊都是整數,如果你非要一個整數%另外一個非整數的可以用強制類型轉換把它裝換成整形。

但事實上,即使分母爲0 ,編譯器也不會編譯錯誤,輸出結果爲inf,表示無窮大。

 

12.

在x86系統下,sizeof如下結構體的值是 4+4 = 8字節

typedef struct list_t{
struct list_t *next;
struct list_t *prev;
char data[0];
}list_t;

柔性數組:
把單一元素的數組放在一個struct的尾端,使得每個struct對象可以擁有可變大小的數組

開始題目中的char data[0] 或寫成char data[],即爲柔性數組;

data不佔用struct的空間,只是作爲一個符號地址存在。

 

13.

class 與 struct 異同

     1.不同點

  struct class
默認繼承權限 public private
默認數據訪問控制 public private
模板參數 不能定義 可以用於定義模板參數

     2.相同點

     可以有數據成員,方法,構造函數等。

 

14.

編譯把一個源程序翻譯成目標程序的工作過程分爲五個階段:詞法分析;語法分析;語義檢查和中間代碼生成;代碼優化;目標代碼生成。按照編譯的工作內容推斷編譯錯誤可分爲詞法錯誤和語法錯誤

 

15.

c中的函數申明爲 int abs(int num);

正常情況下,

num爲0或正數時,函數返回num值;

當num爲負數且不是最小的負數時(不要問我最小的int類型負數是多少,上面那個圖裏面有真相),函數返回num的對應絕對值數,即將內存中該二進制位的符號位取反,並把後面數值位取反加一;

當num爲最小的負數時(即0x80000000),由於正數裏int類型32位表示不了這個數的絕對值,所以依然返回該負數。

 

16.

C++中如果聲明一個對象指針時沒有分配內存,那麼不會調用構造函數

class Sample
{
public:
   Sample(){cout<<"S ";}
  ~Sample(){cout<<"~S ";}
};
int main( )
{   Sample Temp ,*pTemp[2];
   return 0;
}

 

17.

對於模板類中的static 數據, 每個不同類型的模板(int 或者 double)都是各自生成一個自己的類模板

#include <iostream>
using namespace std;
template <typename T>
class example
{ private:
       static int num;
	   T data;
   public:
      example(T x){data=x;num++;cout<<"in "<<num<<endl;}
     ~example(){
         num--;
         cout<<"num = "<< num<<'\t';
         cout<<"this->"<<data<<endl;
     }
};
template<typename T> int example<T>::num=0;
int main()
{  example<double> object1(3.5);
   example<int> object2(9);
   example<int> object3(5);
   return 0;
}

 

18.

設串中字符數爲n,則其子串數目爲:s=(1+n)*n/2+1

 

19.

n個結點的m叉樹空指針個數: m*n-(n-1)=(m-1)*n+1

n個結點爲一棵樹則有n-1條邊,因此有n-1個非空指針,而空指針個數m*n-(n-1)=3*n+1

 

20.

CSomething a();// 沒有創建對象,這裏不是使用默認構造函數,而是定義了一個函數,在C++ Primer393頁中有說明。

CSomething b(2);//使用一個參數的構造函數,創建了一個對象。

CSomething c[3];//使用無參構造函數,創建了3個對象。

CSomething &ra=b;//ra引用b,沒有創建新對象。

CSomething d=b;//使用拷貝構造函數,創建了一個新的對象d。

CSomething *pA = c;//創建指針,指向對象c,沒有構造新對象。

CSomething *p = new CSomething(4);//新建一個對象

CSomething *pB;  //創建指針,沒有構造新對象。

 

21.

如果一個派生類從多個基類派生,而這些基類又有一個共同     的基類,則在對該基類中聲明的名字進行訪問時,可能產生二義性。虛基類的提出就是爲了解決此類問題。

如果在多條繼承路徑上有一個公共的基類,那麼在繼承路徑的某處匯合點,這個公共基類就會在派生類的對象中產生多個基類子對象,要使這個公共基類在派生類中只產生一個子對象,必須對這個基類聲明爲虛繼承,使這個基類成爲虛基類.

 

22.

重載:

    只有在 同一類定義中的同名成員函數才存在重載關係 ,主要特點是 函數的參數類型和數目有所不同 ,但 不能出現函數參數的個數和類型均相同 ,僅僅依靠返回值類型不同來區分的函數,這和普通函數的重載是完全一致的。另外,重載和成員函數是否是虛函數無關

覆蓋:

    派生類中覆蓋基類中的同名函數,要求兩個函數的參數個數、參數類型、返回類型都相同,且基類函數必須是虛函數

隱藏:

  派生類中的函數屏蔽了基類中的同名函數,2個函數參數相同,但基類函數不是虛函數(和覆蓋的區別在於基類函數是否是虛函數)。2個函數參數不同,無論基類函數是否是虛函數,基類函數都會被屏蔽(和重載的區別在於兩個函數不在同一類中)。

https://blog.csdn.net/aron_conli/article/details/88239217

 

23.

因爲const對象以及引用只能初始化而不能賦值,所以只能使用成員初始化列表。

對於非內置類型,在進入函數體之前,如果沒有提供顯式初始化,會調用默認構造函數進行初始化。若沒有默認構造函數,則編譯器嘗試調用默認構造函數將會失敗,所以如果沒有默認構造函數,則必須在初始化列表中顯示的調用構造函數。

static 成員在執行構造函數前就已經構造好了,即使不存在類對象,也可以被使用,不需要初始化列表

 

24.

       

 

Ø 派生類指針只有經過強制類型轉換之後,才能引用基類對象

Ø基類指針雖然獲取派生類對象地址,卻只能訪問派生類從基類繼承的成員

 

25. 虛函數

Ø 一個虛函數,在派生類層界面相同的重載函數都保持虛特性

Ø 虛函數必須是類的成員函數

Ø 不能將友元說明爲虛函數,但虛函數可以是另一個類的友元

Ø 析構函數可以是虛函數,但構造函數不能是虛函數

  1. 構造函數不能是虛函數。建立一個派生類對象時,必須從類層次的根開始,沿着繼承路徑逐個調用基類的構造函數
  2. 析構函數可以是虛的。虛析構函數用於指引 delete 運算符正確析構動態對象
  3. 設計類層次結構時,提供一個虛析構函數,能夠使派生類對象在不同狀態下正確調用析構函數。

虛函數重載特性

Ø 在派生類中重載基類的虛函數要求函數名、返回類型、參數個數、

  參數類型和順序完全相同

Ø 如果僅僅返回類型不同,C++認爲是錯誤重載

Ø 如果函數原型不同,僅函數名相同,丟失虛特性

 

26. 純虛函數和抽象類

Ø  純虛函數是一個在基類中說明的虛函數,在基類中沒有定義,

   要求任何派生類都定義自己的版本

Ø  純虛函數爲各派生類提供一個公共界面

Ø  純虛函數說明形式:    virtual  類型  函數名參數表= 0 ;

Ø 一個具有純虛函數的基類稱爲抽象類。

shape  x ;    // error,抽象類不能建立對象

shape  *p ;  // ok,可以聲明抽象類的指針

shape  f ( ) ;  // error, 抽象類不能作爲函數返回類型

void  g ( shape ) ;    // error, 抽象類不能作爲傳值參數類型

shape  & h ( shape &) ;  // ok,可以聲明抽象類的引用

                                      // 也不能建立抽象類型存儲空間

Ø虛函數和多態性使軟件設計易於擴充。

Ø派生類重載基類接口相同的虛函數其虛特性不變。

Ø如果代碼關聯在編譯時確定,稱爲靜態聯編。代碼在運行時關聯稱爲動態聯編。

Ø基類指針可以指向派生類對象、基類中擁有虛函數,是支持多態性的前提。

Ø虛析構函數可以正確釋放動態派生類對象的資源。

Ø純虛函數由派生類定義實現版本。

Ø具有純虛函數的類稱爲抽象類。抽象類只能作爲基類,不能建立對象。抽象類指針使得派生的具體類對象具有多態操作能力。

 

27.

 燙燙燙和屯屯屯產生自VC,這是debug模式下VC對內存的初始化操作。VC會把棧中新分配的內存初始化爲0xcc,而把堆中新分配的內存初始化爲0xcd。(0xcc恰好是終端指令int 3,算是保護嗎?)把0xcc和0xcd按照字符打印出來,就是燙和屯了

 

28.

  回調函數就是一個通過函數指針調用的函數: 如果你把函數的指針(地址)作爲參數傳遞給另一個函數,當這個指針被用來調用其所指向的函數時,我們就說這是回調函數。 回調函數不是由該函數的實現方法直接調用,而是在特定的事件或條件發生時由另外的一方調用的,用於對該事件或條件進行響

類的成員函數需要隱含的this指針 而回調函數沒有辦法提供。

回調函數還真有點像BP機:告訴別人號碼,在它有事情時Call您 
回調用於層間協作,上層將本層函數安裝在下層,這個函數就是回調,而下層在一定條件下觸發回調,例如作爲一個驅動,是一個底層,他在收到一個數據時,除了完成本層的處理工作外,還將進行回調,將這個數據交給上層應用層來做進一步處理,這在分層的數據通信中很普遍。 
其實回調和API非常接近,他們的共性都是跨層調用的函數。但區別是API是低層提供給高層的調用,一般這個函數對高層都是已知的;而回調正好相反,他是高層提供給底層的調用,對於低層他是未知的,必須由高層進行安裝,這個安裝函數其實就是一個低層提供的API,安裝後低層不知道這個回調的名字,但它通過一個函數指針來保存這個回調,在需要調用時,只需引用這個函數指針和相關的參數指針。其實:回調就是該函數寫在高層,低層通過一個函數指針保存這個函數,在某個事件的觸發下,低層通過該函數指針調用高層那個函數。

 

29.

對於一維數組,這句話是對的。

作爲實參:

一維數組的定義不需要定義長度,系統有時候可以自己判斷長度,比如:int a[] = {1,2};

作爲形參:

在函數的形參定義時,有沒有長度無所謂,參數傳遞是以指針形式實現的;比如void fun(int a[]){}

 

二維數組則不同:

作爲實參:

二維數組定義的時候,一定要給定第二維(列)的長度!

作爲形參:

假如定義了int a[2][3],這裏的a不是二級指針int **p,而是表示數組指針,

也就是說a是指向大小爲3的一維數組的指針,(a+1)則是下一個大小爲3的一維數組的指針……

形參中,可以表示數組指針的形式只有void fun( p[2][3] ){}形式!(2可以省略)

(請教一下怎麼在這裏改變字體顏色?總不能每次都在word裏面改好再複製過來吧?)

 

舉個例子:

假如你定義了二維數組int a[2][3] = {...},想要調用fun(a),你傳遞就是數組指針,

你的定義可能如下:

A. void fun( int **p ) {}

在fun(a)的a下面標記錯誤:int(*)[3]類型的實參和int **類型的形參不符;

B. void fun( int *p[ ] ) {}

報錯和A完全相同:形參會把[]退化成指針,這相當於定義了形參爲二級指針;

C. void fun( int *p[3] ){}

報錯如上:形參不會識別[ ]中的3;

D. void fun( int p[ ][ ] ) {}

在p[ ][ ]定義錯誤,什麼時候都不能出現p[ ][ ],因爲第二維不能爲空;

E. void fun( int p[2][3] ){}

正確,這是我知道的,唯一的,符合“實參是數組指針”的形參的定義形式;2可有可無。

 

綜上:

二維數組名a其實是(一維數組)指針,而不是二級指針!

假如自己編代碼用到數組是實參,可以定義形參和實參完全一樣,可以省去不少麻煩而且不會出錯。

 

30.

C語言中的可變參數-printf的實現原理

在C/C++中,對函數參數的掃描是從後向前的。C/C++的函數參數是通過壓入堆棧的方式來給函數傳參數的(堆棧是一種先進後出的數據結構),最先壓入的參數最後出來,在計算機的內存中,數據有2塊,一塊是堆,一塊是棧(函數參數及局部變量在這裏),而棧是從內存的高地址向低地址生長的,控制生長的就是堆棧指針了,最先壓入的參數是在最上面,就是說在所有參數的最後面,最後壓入的參數在最下面,結構上看起來是第一個,所以最後壓入的參數總是能夠被函數找到,因爲它就在堆棧指針的上方。printf的第一個被找到的參數就是那個字符指針,就是被雙引號括起來的那一部分,函數通過判斷字符串裏控制參數的個數來判斷參數個數及數據類型,通過這些就可算出數據需要的堆棧指針的偏移量了,下面給出printf("%d,%d",a,b);(其中a、b都是int型的)的彙編代碼.

 

31.

int a[5]={1,2,3,4,5};

int *ptr=(int*)(&a+1);

a 代表的是int * 每次步長爲一個int                        &a 代表的是 int[]* 每次步長爲所指向的數組的大小

 

32. static總結:

一、靜態成員的特點:

(1)static數據成員在類的內部聲明,但只能在類的外部定義,在類的外部不能指定static,在類的定義時候進行初始化;

(2)static數據成員只能在類的外部進行初始化(特例:當整型const static數據成員被常量表達式初始化時,就可以在類的內部進行初始化,但還需要在外部進行定義)。

(3) static數據成員可以是該成員所屬的類類型,而非static數據成員只能自身類的引用或者指針。

(4)static數據成員可以用作類成員函數的默認實參。

(5)static數據成員的值可以改變。

二、靜態成員和非靜態成員的區別:

(1) 靜態變量使用 static 修飾符進行聲明,在類被實例化時創建,通過類和對象都可以進行訪問;

(2)不帶有 static 修飾符聲明的變量稱做非靜態變量,在對象被實例化時創建,通過對象訪問;

(3) 一個類的所有實例的同一靜態變量都是同一個值,同一個類的不同實例的同一非靜態變量可以是不同的值。

(4) 靜態函數的實現裏不能使用非靜態成員,如非靜態變量、非靜態函數等。

三、靜態成員函數的特點:

(1) static 成員函數沒有 this 形參,它可以訪問所屬類的 static 成員,但不能訪問非 static 成員。

(2)static成員函數既可以在類的內部定義,也可以在類的外部定義,在外部定義時,不能重複指定static保留字。

(3)static成員函數不能聲明爲虛函數,不能實現動態綁定

(4)static 成員函數不能聲明爲const,因爲const是針對this是不是const而言的

(5)構造函數、析構函數不能爲靜態函數

 

33.

宏定義是在編譯器預處理階段中就進行替換了,替換成什麼只與define和undefine的位置有關係,與它們在哪個函數中無關

問題:https://www.nowcoder.com/questionTerminal/6123927513b241f8ba2b864ecb1cfc0e

 

34.

首先 #include<> 和 #include"" 只是最先搜索的路經不一樣。
#include<>  :表示只從從標準庫文件目錄下搜索,對於標準庫文件搜索效率快。
#include""    :表示首先從用戶工作目錄下開始搜索,對於自定義文件搜索比較快,然後擴展到標準庫路徑。 

 

35.

C/C++規定,一個數如果要指明它採用八進制,必須在它前面加上一個0,如:123是十進制,但0123則表示採用八進制。這就是八進制數在C、C++中的表達方法

int i=010,j=10;
-->i = 8 
-->j = 10

 

36.

C語言中,字符串必須是以’\0'結尾。在答案A中,s定義爲5個元素的字符型數組,即最多能存放5個字符,字符串結尾符’\0’無法存放,故A是錯誤的字符串賦值;答案B對數組賦值沒錯,但同A一樣,沒有字符串結尾符’\0’,所以也是錯誤的;答案D是“野指針”賦值,是錯誤的:而對於答案C,先定義字符指針s,而後將字符串"ABCDE”的首地址賦值給指針變量s,是正確的賦值.

 

37.

 auto根據數據類型分配內存,register在使用到時分配CPU寄存器地址 

 

38.

typedef struct ST{

    long a; int b; char c[2];

} NEW;

如果前面沒有typedef, 則ST是結構體類型,NEW是結構體變量;

如果有typedef,則ST和NEW都是結構體類型;

 

38.

a++返回的是一個temp,並不是用戶定義的那種可以引用、尋址的變量,不能對其操作,只能用來賦值

++a返回的是一個變量,還是a,可以當做左值。

https://www.nowcoder.com/test/question/done?tid=21996026&qid=156773#summary

 

39

數據類型關鍵字(12個):

(1) char :聲明字符型變量或函數
(2) double :聲明雙精度變量或函數
(3) enum :聲明枚舉類型
(4) float:聲明浮點型變量或函數
(5) int: 聲明整型變量或函數
(6) long :聲明長整型變量或函數
(7) short :聲明短整型變量或函數
(8) signed:聲明有符號類型變量或函數
(9) struct:聲明結構體變量或函數
(10) union:聲明共用體(聯合)數據類型
(11) unsigned:聲明無符號類型變量或函數
(12) void :聲明函數無返回值或無參數,聲明無類型指針(基本上就這三個作用)

控制語句關鍵字(12個):

循環語句
(1) for:一種循環語句(可意會不可言傳)
(2) do :循環語句的循環體
(3) while :循環語句的循環條件
(4) break:跳出當前循環
(5) continue:結束當前循環,開始下一輪循環
條件語句
(1)if: 條件語句
(2)else :條件語句否定分支(與 if 連用)
(3)goto:無條件跳轉語句
開關語句
(1)switch :用於開關語句
(2)case:開關語句分支
(3)default:開關語句中的“其他”分支
返回語句
return :子程序返回語句(可以帶參數,也看不帶參數)

存儲類型關鍵字(4個):

(1)auto :聲明自動變量 一般不使用
(2)extern:聲明變量是在其他文件正聲明(也可以看做是引用變量)
(3)register:聲明寄存器變量
(4)static :聲明靜態變量

其它關鍵字(4個):

(1)const :聲明只讀變量
(2)sizeof:計算數據類型長度
(3)typedef:用以給數據類型取別名(當然還有其他作用
(4)volatile:說明變量在程序執行中可被隱含地改變

 

40.

字符是C語言的最小單位

 

50.

這種情況出現在多任務系統當中,在任務執行期間捕捉到 信號 並對其進行處理時,進程正在執行的指令序列就被信號處理程序臨時 中斷。如果從信號處理程序返回,則繼續執行進程斷點處的正常指令序列,從重新恢復到斷點重新執行的過程中,函數所依賴的環境沒有發生改變,就說這個函數是 可重入 的,反之就是 不可重入 的。

滿足下麪條件之一的多數是不可重入函數: 
(1)使用了靜態數據結構; 
(2)調用了malloc或free; 
(3)調用了標準I/O函數;標準io庫很多實現都以不可重入的方式使用全局數據結構。 
(4)進行了浮點運算.許多的處理器/編譯器中,浮點一般都是不可重入的 (浮點運算大多使用協處理器或者軟件模擬來實現

 

51.

看如何用const 很多同志都分享什麼就近原則啊,看這個看那個,,我真想說好累的記法!
看我的方法:
如:  int  const *  const p;
找到第一個const,  後面除了有個const之外 就是 *  和 p,  那麼見證奇蹟的時刻來了,
const  *  p  這就是我們要的結果,p指向的內容不可變

找到第二個const,  後面只有個p,   那麼見證奇蹟的時候到了
const  p,,這就是結果, p不可變

++規則總結如下:找到const, 再看後面除了const的內容,是什麼東西,那個東西不能變即是

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章