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)三數取中或者無數取中法;
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/96284.html
標籤:C++
