c++項目經驗分享


1、C++的const比C語言#define更好的原因?

首先,它能夠明確指定類型,有類型檢查功能。

其次,可以使用C++的作用域規則將定義限制在特定的函數[常函數]或文件中。

第三,可以將const用於更復雜的類型,比如數組和結構。

C語言中也有const,在C語言中分配內存,其與C++中const的區別是:一是作用域規則不同;另一個是,在C++中可以用const值來聲明數組長度。在C++中const在沒有取地址和加extern時,是不分配內存空間的,和#define有相同的效果,常量折疊。

注意:外部要能訪問test.cpp中的const形式的n, 必須在test.cpp中定義的時候用extern限定。

test.cpp

extern const int n = 100;  //必須加extern

#include <iostream> 

using namespace std; 

extern const int n; 

int main() 

   cout << n << endl; 

   return 0; 

} </iostream>

2、逗號運算符

逗號運算符的特性有下面幾個:

(1)它確保先計算第一個表達式,然后計算第二個表達式;

i = 20, j = 2 * i; // i set to 20, then jset to 40

(2)逗號表達式的值是第二部分的值。例如,上面表達式的值為40。在所有運算符中,逗號運算符的優先級是最低的。例如:

cats = 17, 240; //被解釋為:(cats =17), 240;

也就是說,將cats設置為17,后面的240不起作用。如果是:

cats = (17, 240); //cats=240。

3、不能簡單地將整數賦給指針,如下所示:

int *ptr;

ptr = 0x12342342;  // type mismatch

在這里,左邊是指向int的指針,但右邊是一個整數。在C99標准發布之前,C語言允許這樣賦值。但C++在類型一致方面的要求更嚴格,編譯器將顯示一條錯誤消息,通告類型不匹配。要將數字值作為地址來使用,應通過強制類型轉換將數字轉換為適當的地址類型:

int *ptr;

ptr = (int *) 0x12342342;  // type now match

這樣,賦值語句的兩邊都是整數的地址,因此這樣賦值有效。但是這樣做很危險。隨意的數值可能是指向系統的重要文件,這樣就會是系統崩潰。

注意,pt是int值的地址並不意味着pt本身的類型是int。例如,在有些平台中,int類型是個2字節值,而地址是個4字節值。

4、C++的多態性分為靜態多態和動態多態。

靜態多態性:編譯期間確定具體執行哪一項操作,主要是通過函數重載和運算符重載來實現的;

動態多態性:運行時確定具體執行哪一項操作,主要是通過虛函數來實現的。

5、下面的程序輸出結果是多少?

#include

int main()

{

int x=2,y,z;

x *=(y = z = 5); printf(“%d\n”,x); //10

z = 3;

x ==(y = z); printf(“%d\n”,x); //10

x =(y == z); printf(“%d\n”,x); //1

x = (y&z); printf(“%d\n”,x); // 與運算 3

x = (y&&z); printf(“%d\n”,x); //1

y = 4;

x = (y | z); printf(“%d\n”,x);//或運算 7

x = (y || z); printf(“%d\n”,x);//1

return 0;

}

6.下面的程序輸出結果是多少?

#include

main()

{

int b = 3;

int arr[] = {6,7,8,9,10};

int *ptr = arr;

*(ptr++)+=123;//先算等號右邊再算左邊的;

//*ptr=*ptr+_123; 即arr[0]=129;

//千萬不要認為是:*(ptr++)=*(ptr++)+123;

//還有就是要認清++和--的作用;

printf(“%d,%d\n”,*ptr,*(++ptr)); //8 8

//printf函數的運算設計到進棧和出棧,運算順序是從右向左;

//先算*(++ptr),后算*ptr;

printf("%d\n",arr[0]); //129

}

7、C++存儲方案:C++三種,C++11四種

這些方案的區別就在於數據保留在內存中的時間。

自動存儲持續性:在函數定義中聲明的變量(包括函數參數)的存儲持續性為自動的。它們在程序開始執行其所屬的函數或代碼塊時被創建,也即用到時分配內存,在執行完函數或代碼塊時,它們使用的內存被釋放回收,且能夠重復使用。C++有兩種存儲持續性為自動的變量。

靜態存儲持續性:在函數定義外定義的變量和使用關鍵字static定義的變量的存儲持續性都為靜態。它們在程序整個運行過程中都存在,且靜態變量一開始就在內存中。C++有3種存儲持續性為靜態的變量。

動態存儲持續性:用new運算符分配的內存將一直存在,直到使用delete運算符將其釋放或程序結束為止。這種內存的存儲持續性為動態,有時被稱為自由存儲(free store)或堆(heap)。

線程存儲持續性(C++11):當前,多核處理器很常見,這些CPU可同時處理多個執行任務。這讓程序能夠將計算放在可並行處理的不同線程中。如果變量是使用關鍵字thread_local聲明的,則其生命周期與所屬的線程一樣長。本書不探討並行編程。

8、自己寫string類注意事項:

CString & CString::operator=(constCString &st)

{

 if(this == & st) 

   return * this;

 delete [] str;

 len= st.len;

 str= new char [len + 1];

 strcpy(str,st.str);

 return *this;

}

主要注意一下四點:

(1)、是否把返回值類型聲明為該類型的引用?並在結束前是否返回該實例自身的引用(保證連續賦值);

(2)、是否把參數設置為const &?(否則會調用拷貝構造函數,其次防止意外改變參數)

(3)、是否記得釋放自身的內存?(否則會內存泄露,指針指向了其他的地方)

(4)、是否進行了實例對象的等值判斷,是否為同一個實例?(否則釋放實例的時候,將參數的內存頁釋放,找不到賦值對象引起錯誤)

9、虛函數原理考點,例如下面程序的輸出是什么?

class A {

public:

   virtual void funa();

   virtual void funb();

   void func();

   static void fund();

   static int si;

private:

   int i;

   char c;

};

問:sizeof(A) = ?

解答:

關於類占用的內存空間,有以下幾點需要注意:

(1)如果類中含有虛函數,則編譯器需要為類構建虛函數表,類中需要存儲一個指針指向這個虛函數表的首地址,注意不管有幾個虛函數,都只建立一張表,所有的虛函數地址都存在這張表里,類中只需要一個指針指向虛函數表首地址即可。

(2)類中的靜態成員是被類所有實例所共享的,它不計入sizeof計算的空間

(3)類中的普通函數或靜態普通函數都存儲在棧中,不計入sizeof計算的空間

(4)類成員采用字節對齊的方式分配空間

答案:12(32位系統)或16(64位系統)

10、C++中可以重載的運算符:new/delete、new[]/delete[]、++等。

不可以重載的運算符:、.、::、?:、sizeof、typeid、.、**、不能改變運算符的優先級。

11、重載++和–時是怎么區分前綴++和后綴++的?

當編譯器看到++a(先自增)時,它就調用operator++(a)/operator++();

但當編譯器看到a++時,它就調用operator++(a, int) /operator++(int)

[有類型無變量是啞元]。即編譯器通過調用不同的函數區別這兩種形式。

12、在C++中,如果確定了某一個構造函數的創建過程,在該構造函數中如果調用了其它重載的構造函數,它將不會執行其它構造函數的初始化列表部分代碼,而是執行函數體代碼,此時已經退化成普通函數了。例子說明如下:

class CBook {

public:

   double m_price;

   CBook() {

       CBook(8.8);

    }

   CBook(double price) : m_price(price) { }

};

int main() {

   CBook c;

   cout << c.m_price << endl; // 此時並不會輸出理想中的8.8

}

13、C的結構體和C++結構體的區別

(1)C的結構體內不允許有函數存在,C++允許有內部成員函數,且允許該函數是虛函數。所以C的結構體是沒有構造函數、析構函數、和this指針的。

(2)C的結構體對內部成員變量的訪問權限只能是public,而C++允許public,protected,private三種。

(3)C語言的結構體是不可以繼承的,C++的結構體是可以從其他的結構體或者類繼承過來的。

以上都是表面的區別,實際區別就是面向過程和面向對象編程思路的區別:

C的結構體只是把數據變量給包裹起來了,並不涉及算法。

而C++是把數據變量及對這些數據變量的相關算法給封裝起來,並且給對這些數據和類不同的訪問權限。

C語言中是沒有類的概念的,但是C語言可以通過結構體內創建函數指針實現面向對象思想。

14、可作為函數重載判斷依據的有:參數個數、參數類型、const修飾符;

不可以作為重載判斷依據的有:返回類型。

15、如何將一個小數分解成整數部分和小數部分?

要記得利用頭文件中的庫函數modf,下面是函數原型(記住一些實用的庫函數,避免自己重寫):

fractpart= double modf(double num, double*Intpart); // 將num分解為整數部分intpart和小數部分fractpart(返回值決定)

16、易誤解:

如果int a[5], 那么a與&a是等價的,因為兩者地址相同。

解答:一定要注意a與&a是不一樣的,雖然兩者地址相同,但意義類型不一樣,

&a是整個數組對象的首地址,int(*p)[5];因此&a+1相當於a的地址值加上sizeof(int) * 5,也就是a[5],下一個對象的地址,已經越界了;

而a是數組首地址,也就是a[0]的地址,&a[0];a[0]的類型是int,而a+1相當於a的地址加上sizeof(int),即a[1]的地址。

17、注意sizeof不是函數而是運算符,所以在計算變量所占用空間大小時,括號是可以省略的,但在計算類型大小時括號則不能省略:

比如int i = 0; 則

sizeof int; //ERROR

sizeof i=4; //OK

18、快速排序為什么比堆排序效率高?

(1)比較的次數,堆排序比較的次數比快排多;有很多都是無謂的比較,快排每調整一次每個元素都是朝正確的位置進一步,但是堆排序不是,最后一個元素調整到第一個,下次可能又跳回到最后一個;隨機性太大;

(2)cache局部性原理。堆排序都是不相鄰的,數據極不友好,快排都是相鄰的,移動的快,充分利用率cache。

缺點:快排是遞歸調用,消耗的空間較大。

19、數據庫中nchar()和char()、varchar()和nvarchar()的區分?

char[10]

是定長的,也就是當你輸入的字符小於你指定的數目8時,它會再后面補空值-'\0'。當你輸入的字符大於指定的數時,它會截取超出的字符。

varchar[10]

長度為 n 個字節的可變長度且非 Unicode 的字符數據。n 必須是一個介於 1 和 8,000 之間的數值。存儲大小為輸入數據的字節的實際長度,而不是 n 個字節。所輸入的數據字符長度可以為零。

例如輸入“hello”,那么氣長度不是10,而是5+1=6,

為什么“+1”呢?這一個字節用於保存實際使用了多大的長度。

nvarchar[10]

包含 n 個字符的可變長度 Unicode 字符數據。n 的值必須介於 1 與 4,000 之間。字節的存儲大小是所輸入字符個數的兩倍。所輸入的數據字符長度可以為零。Unicode字符集就是為了解決字符集這種不兼容的問題而產生的,它所有的字符都用兩個字節表示,即英文字符也是用兩個字節表示。

例如兩字段分別有字段值:我和coffee

那么varchar字段占2×2+6=10個字節的存儲空間,而nvarchar字段占8×2=16個字節的存儲空間。

從空間上考慮,用varchar合適;從效率上考慮,用char合適,關鍵是根據實際情況找到權衡點。

這三種從名字上看比前面三種多了個“N”。它表示存儲的是Unicode數據類型的字符。我們知道字符中,英文字符只需要一個字節存儲就足夠了,但漢字眾多,需要兩個字節存儲,英文與漢字同時存在時容易造成混亂,Unicode字符集就是為了解決字符集這種不兼容的問題而產生的,它所有的字符都用兩個字節表示,即英文字符也是用兩個字節表示。nchar、nvarchar的長度是在1到4000之間。和char、varchar比較起來,nchar、nvarchar則最多存儲4000個字符,不論是英文還是漢字;而char、varchar最多能存儲8000個英文,4000個漢字。可以看出使用nchar、nvarchar數據類型時不用擔心輸入的字符是英文還是漢字,較為方便,但在存儲英文時數量上有些損失。

所以一般來說,選擇標准:如字段值只是英文可選擇varchar,而字段值存在較多的雙字節(中文、韓文等)字符時用nvarchar

優缺點:

char:可以看出,是利用空間換時間,處理比較方便,英文一個字節存儲。

【存儲很短的信息;固定長度的,比如人名,這些步長而且長度大體相當;十分頻繁改變的column。】

varchar:空間效率高,節約內存;但是時間效率有所下降,容易出現內存碎片,尤其當更新時的數據比元數據量大時,比較繁瑣。另外,varchar申請的時候不能過於康概,要按需索取。對於相同的字符串,其存儲空間雖然相同,但是對於內存的消耗是不同的。

20、如何解決在構造函數里統計對象計數不准確的問題?

原因:可能因為拷貝構造函數而產生的對象,這樣就不會調用構造函數。解決辦法,提供一個顯示的賦值構造函數處理計數問題。

student::student(const student &st)

{

num++;

}

21、快排中中值的選取:

(1)固定元素法:取第一個或者最后一個作為partition的pivot。

(2)隨機元素法:隨機生成作為partition的pivot。

(3)三數取中或者無數取中法;


免責聲明!

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



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