char c = '72';
中的72代表1個字符,72是8進制數,代表ASCII碼字符“:”。
10*a++
中a先進行乘法運算再自增(筆試中常常喜歡出這類運算符優先級容易混淆的輸出問題)。
const和static的作用
太常見的問題了,下面給出1個較詳細的參考答案:
static關鍵字:
1)函數體內static變量的作用范圍為函數體。不同于auto變量。該變量的內存只被分配1次。因此其值在下次調用時仍保持上次的值。
2)在模塊內的static全局變量可以被模塊內的所有函數訪問。但不能被模塊外的其他函數訪問。
3)在模塊內的static函數只可被這1模塊內的其它函數調用。這個函數的使用范圍被限制在聲明它的模塊內。
4)在類中的static成員變量屬于全部類所有,對類的所有對象只有1份復制。
5)在類中的static成員函數屬于全部類所有,這個函數不接受this指針,因此只能訪問類的static成員變量。
const關鍵字:
1)欲禁止1個變量被改變,可使用const關鍵字。在定義該const變量時,通常需要對它進行初始化。由于以后就沒有機會再改變它了。
2)對指針來講,可以指定指針的本身為const,也能夠指定指針所指向的數為const。或2者同時為const。
3)在1個函數的聲明中,const可以修飾形參,表明它是1個輸入參數。在函數內不能改變其值。
4)對類的成員函數,若指定其為const類型。則表明其是1個常量函數。不能修改類的成員變量。
5)對類的成員函數,有時候必須指定其返回值為const類型。以使得其返回值不為“左值”。
注意sizeof不是函數而是運算符,所以在計算變量所占用空間大小時,括號是可以省略的,但在計算類型大小時括號則不能省略,比如int i = 0; 則sizeof int是毛病的。
有1,2,…,n的無序數組,求排序算法,并且要求時間復雜度為O(n),空間復雜度O(1),使用交換,而且1次只能交換兩個數。
#include <stdio.h>
int main() {
int a[] = {10, 6, 9, 5, 2, 8, 4, 7, 1, 3};
int i, tmp;
int len = sizeof(a) / sizeof(a[0]);
for(i = 0; i < len;) {
tmp = a[a[i] - 1];
a[a[i] - 1] = a[i];
a[i] = tmp;
if(a[i] == i + 1) i++;
}
for(i = 0; i < len; ++i)
printf("%d ", a[i]);
printf("
");
return 0;
}
易誤解:如果int a[5]
, 那末a與&a是等價的,由于二者地址相同。
解答:1定要注意a與&a是不1樣的,雖然二者地址相同,但意義不1樣,&a是全部數組對象的首地址,而a是數組首地址,也就是a[0]的地址,a的類型是int[5],a[0]的類型是int,因此&a+1相當于a的地址值加上sizeof(int) * 5,也就是a[5],下1個對象的地址,已越界了,而a+1相當于a的地址加上sizeof(int),即a[1]的地址。
如何將1個小數分解成整數部份和小數部份?
要記得利用頭文件中的庫函數modf,下面是函數原型(記住1些實用的庫函數,避免自己重寫):
double modf(double num, double *i); // 將num分解為整數部份*i和小數部份(返回值決定)
可作為函數重載判斷根據的有:參數個數、參數類型、const修飾符;
不可以作為重載判斷根據的有:返回類型。
程序輸出題:
int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int *p = &(a + 1)[3];
printf("%d
", *p);
輸出:5
說明:由于a+1指向a的第2個元素,[3]表示再向后移動3個元素。
程序輸出題:
char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char *str5 = "abc";
const char *str6 = "abc";
char *str7 = "abc";
char *str8 = "abc";
cout << (str1 == str2) << endl;
cout << (str3 == str4) << endl;
cout << (str5 == str6) << endl;
cout << (str7 == str8) << endl;
輸出:0 0 1 1
說明:輸出str1~str8的地址為:
0x23aa80
0x23aa70
0x23aa60
0x23aa50
0x23aa48
0x23aa40
0x23aa38
0x23aa30
輸出str1~str8內容“abc”的存儲地址為:
0x23aa80
0x23aa70
0x23aa60
0x23aa50
0x100403030
0x100403030
0x100403030
0x100403030
可以發現str1~str4中的內容是存在棧上,地址各不相同,而str5~str8的內容都是存儲在常量區,所以地址都相同。
注意:
char *str = "abc";
printf("%p
", str1);
cout << &str1 << endl;
上面打印的是字符串 “abc”的地址,下面打印的是 str1 變量的地址。
C的結構體和C++結構體的區分
(1)C的結構體內不允許有函數存在,C++允許有內部成員函數,且允許該函數是虛函數。所以C的結構體是沒有構造函數、析構函數、和this指針的。
(2)C的結構體對內部成員變量的訪問權限只能是public,而C++允許public,protected,private3種。
(3)C語言的結構體是不可以繼承的,C++的結構體是可以從其他的結構體或類繼承過來的。
以上都是表面的區分,實際區分就是面向進程和面向對象編程思路的區分:
C的結構體只是把數據變量給包裹起來了,其實不觸及算法。
而C++是把數據變量及對這些數據變量的相干算法給封裝起來,并且給對這些數據和類不同的訪問權限。
C語言中是沒有類的概念的,但是C語言可以通過結構體內創建函數指針實現面向對象思想。
如何在類中定義常量成員并為其初始化?
解答:只能在初始化列表里對const成員初始化,像下面這樣:
class CBook {
public:
const double m_price;
CBook() :m_price(8.8) { }
};
下面的做法是毛病的:
class CBook {
public:
const double m_price;
CBook() {
m_price = 8.8;
}
};
而下面的做法雖未報錯,但有個warning,也不推薦:
class CBook {
public:
const double m_price = 8.8; // 注意這里若沒有const則編譯出錯
CBook() { }
};
在定義類的成員函數時使用mutable關鍵字的作用是甚么?
解答:當需要在const方法中修改對象的數據成員時,可以在數據成員前使用mutable關鍵字,避免出現編譯出錯。例子以下:
class CBook {
public:
mutable double m_price; // 如果不加就會出錯
CBook(double price) :m_price(price) { }
double getPrice() const; // 定義const方法
};
double CBook::getPrice() const {
m_price = 9.8;
return m_price;
}
構造函數、拷貝構造函數、析構函數的調用點溫柔序問題,以下面這個例子輸出是甚么?
class CBook {
public:
CBook() {
cout << "constructor is called.
";
}
~CBook() {
cout << "destructor is called.
";
}
};
void invoke(CBook book) { // 對象作為函數參數,如果這里加了個&就不是了,由于加了&后是援用方式傳遞,形參和實參指向同1塊地
// 址,就不需要創建臨時對象,也就不需要調用拷貝構造函數了
cout << "invoke is called.
";
}
int main() {
CBook c;
invoke(c);
}
解答:注意拷貝構造函數在對象作為函數參數傳遞時被調用,注意是對象實例而不是對象援用。因此該題輸出以下:
constructor is called.
invoke is called.
destructor is called. // 在invoke函數調用結束時還要釋放拷貝構造函數創建的臨時對象,因此這里還調用了個析構函數
destructor is called.
引伸:拷貝構造函數在哪些情況下被調用?
(1)函數的參數為類對象且參數采取值傳遞方式;
(2)將類對象做為函數的返回值。
C++中的explicit關鍵字有何作用?
解答:制止將構造函數作為轉換函數,即制止構造函數自動進行隱式類型轉換。
例如CBook中只有1個參數m_price,在構建對象時可使用CBook c = 9.8這樣的隱式轉換,使用explicit避免這類轉換產生。
在C++中,如果肯定了某1個構造函數的創建進程,在該構造函數中如果調用了其它重載的構造函數,它將不會履行其它構造函數的初始化列表部份代碼,而是履行函數體代碼,此時已退化成普通函數了。例子說明以下:
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
}
靜態數據成員只能在全局區域進行初始化,而不能在類體中進行(構造函數中初始化也不行),且靜態數據成員不觸及對象,因此不受類訪問限定符的限制。
例子說明以下:
class CBook {
public:
static double m_price;
};
double CBook::m_price = 8.8; // 只能在這初始化,不能在CBook的構造函數或直接初始化
C++中可以重載的運算符:new/delete、new[]/delete[]、++等。
不可以重載的運算符:、.、::、?:、sizeof、typeid、.、**、不能改變運算符的優先級。
引伸:重載++和
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈