C++经典面试题
1、int a=5,則 ++(a++)的值是()
A、5????? B、?? 6????????? C、7?????? D、邏輯錯誤
a++返回的是一個臨時變量,這里是右值,不能再前面++了
2、下面的代碼輸出什么?(取地址運算符比+運算符的優先級要高)
&a是一個指向數組的指針(行指針),a的步長就是數組的長度。也就是說執行a+1時,a要跨過n個整型數據的長度,輸出*ptr就會發現越界了,是一個隨機值,那么ptr-1的值就是數組的最后一個值了。
&a+1不是首地址+1, 系統會認為加一個a數組的偏移, 是偏移了一個數組的大小(本例是5個int )
int *ptr = (int *)(&a+1);
則ptr實際上是&(a[5]),也就是a+5
原因如下:
&a 是數組指針, 其類型為int (*)[5];
而指針加1要根據指針類型加上一定的值, 不同類型的指針+1之后增加的大小不同。
a 是長度為5的int數組指針,所以要加5*sizeof(int)
所以,ptr實際是ptr[5]
但是ptr與(&a+1)類型時不一樣的(這點很重要)
所以ptr-1只會減去sizeof(int *)
a, &a的地址是一樣的,但是意思不一樣
a是數組首地址,也就是a[0]的地址,&a是對象(數組)首地址
a+1是數組下一元素的地址,即a[1], &a+1是下一個對象的地址,即a[5].
3、以下三條輸出語句分別輸出什么? char str1[] = "abc";char str2[] = "abc";const char str3[] = "abc";const char str4[] = "abc";const char* str5 = "abc";const char* str6 = "abc";cout << boolalpha << ( str1==str2 ) << endl; // 輸出什么?cout << boolalpha << ( str3==str4 ) << endl; // 輸出什么?cout << boolalpha << ( str5==str6 ) << endl; // 輸出什么?
答:分別輸出false,false,true。str1和str2都是字符數組,每個都有其自己的存儲區,它們的值則是各存儲區首地址,不等;str3和str4同上,只是按const語義,它們所指向的數據區不能修改。str5和str6并非數組而是字符指針,并不分配存儲區,其后的“abc”以常量形式存于靜態數據區,而它們自己僅是指向該區首地址的指針,所以相等。
4、下面代碼的輸出是什么?
float a = 1.0f;cout<< (int)a <<endl;cout<< (int&)a <<endl;cout << boolalpha << ( (int)a==(int&)a ) << endl; // 輸出什么?float b = 0.0f;cout<< (int)b <<endl;cout<< (int&)b <<endl;cout << boolalpha << ( (int)b==(int&)b ) << endl; // 輸出什么?浮點數的 1.0f 在內存里是這樣表示的:
0011 1111 1000 0000 00000000 00000000
這個32位二進制數被當作整數輸出就是:
1065353216
而整數的 1 在內存里是這樣表示的:
0000 0000 0000 0000 00000000 00000001
所以 (int)a != (int&)a
浮點的0和整數的0 在內存里都是:
0000 0000 0000 0000 00000000 00000000
所以 (int)b == (int&)b
5、以下代碼中的兩個sizeof用法有問題嗎?
void UpperCase( char str[] ) // 將str 中的小寫字母轉換成大寫字母 {for( size_t i=0; i<sizeof(str)/sizeof(str[0]); ++i ){if( 'a'<=str[i] && str[i]<='z' ){str[i] -= ('a'-'A' );}} } int main(void) {char str[] = "aBcDe";cout << "str字符長度為: " << sizeof(str)/sizeof(str[0]) << endl;UpperCase( str );cout << str << endl;return 0; } 6、非C++內建型別A和B,在哪幾種情況下B能隱式轉化為A?
7、以下代碼有什么問題?
struct Test {Test(int ) { }Test() { }void fun() { } };int main(void) {Test a(1);a.fun();Test b();b.fun();return 0; } 8、 以下代碼有什么問題? cout<< (true?1:"0") <<endl;
9、以下代碼能夠編譯通過嗎,為什么?
int main(void) {unsigned int const size1 = 2;char str1[ size1 ];unsigned int temp = 0;cin >> temp;unsigned int const size2 = temp;char str2[ size2 ];return 0; } 10、以下反向遍歷array數組的方法有什么錯誤?int main(void) {vector array;array.push_back( 1 );array.push_back( 2 );array.push_back( 3 );for( vector::size_type i=array.size()-1; i>=0; --i ) // 反向遍歷array數組{cout << array[i] << endl;}return 0; }
11、以下代碼中的輸出語句輸出嗎,為什么?
struct CLS {int m_i;CLS(int i): m_i( i ) { }CLS(){CLS( 0 );} };int main(void) {CLS obj;cout << obj.m_i << endl;return 0; } 12、C++中的空類,默認產生哪些類成員函數?13、 以下代碼有什么問題嗎?
int main(void) {typedef vector IntArray;IntArray array;array.push_back( 1 );array.push_back( 2 );array.push_back( 2 );array.push_back( 3 );// 刪除array數組中所有的2for( IntArray::iterator itor=array.begin(); itor!=array.end(); ++itor ){if( 2 == *itor ){array.erase( itor );}}return 0; } 14、 寫一個函數,完成內存之間的拷貝。[考慮問題是否全面]
答案:
4、分別輸出false和true。注意轉換的應用。(int)a實際上是以浮點數a為參數構造了一個整型數,該整數的值是,(int&)a則是告訴編譯器將a當作整數看(并沒有做任何實質上的轉換)。因為以整數形式存放和以浮點形式存放其內存數據是不一樣的,因此兩者不等。對b的兩種轉換意義同上,但是的整數形式和浮點形式其內存數據是一樣的,因此在這種特殊情形下,兩者相等(僅僅在數值意義上)。
? 注意,程序的輸出會顯示(int&)a=1065353216,這個值是怎么來的呢?前面已經說了,以浮點數形式存放在內存中,按ieee754規定,其內容為x0000803F(已考慮字節反序)。這也就是a這個變量所占據的內存單元的值。當(int&)a出現時,它相當于告訴它的上下文:“把這塊地址當做整數看待!不要管它原來是什么。”這樣,內容x0000803F按整數解釋,其值正好就是(十進制數)。
? 通過查看匯編代碼可以證實“(int)a相當于重新構造了一個值等于a的整型數”之說,而(int&)的作用則僅僅是表達了一個類型信息,意義在于為cout<<及==選擇正確的重載版本。
5、答:函數內的sizeof有問題。根據語法,sizeof如用于數組,只能測出靜態數組的大小,無法檢測動態分配的或外部數組大小。函數外的str是一個靜態定義的數組,因此其大小為,函數內的str實際只是一個指向字符串的指針,沒有任何額外的與數組相關的信息,因此sizeof作用于上只將其當指針看,一個指針為個字節,因此返回。
6、答:
a. class B : public A { ……} // B公有繼承自A,可以是間接繼承的
b. class B { operator A( ); } // B實現了隱式轉化為A的轉化
c. class A { A( const B& ); } // A實現了non-explicit的參數為B(可以有其他帶默認值的參數)構造函數
d. A& operator= ( const A& ); // 賦值操作,雖不是正宗的隱式類型轉換,但也勉強算一個
7、答:變量b定義出錯。按默認構造函數定義對象,不需要加括號。
8、答:三元表達式“?:”問號后面的兩個操作數必須為同一類型。
9、答:str2定義出錯,size2非編譯器期間常量,而數組定義要求長度必須為編譯期常量。
10、答:首先數組定義有誤,應加上類型參數:vector<int> array。其次vector::size_type被定義為unsigned int,即無符號數,這樣作為循環變量的i為0時再減就會變成最大的整數,導致循環失去控制。
int main(void) {vector<int> array;array.push_back(1);array.push_back(2);array.push_back(3);for(int i = array.size() - 1 ; i >= 0 ; --i)cout<<array[i]<<endl;return 0; } 11、答:不能。在默認構造函數內部再調用帶參的構造函數屬用戶行為而非編譯器行為,亦即僅執行函數調用,而不會執行其后的初始化表達式。只有在生成對象時,初始化表達式才會隨相應的構造函數一起調用。
12、 class Empty { public:Empty(); //缺省構造函數Empty(const Empty &); //拷貝構造函數~Empty(); //析構函數Empty & operator=(const Empty &); //賦值運算符Empty* operator&(); //取址運算符const Empty* operator&() const; //取址運算符const }; 13、答:同樣有缺少類型參數的問題。另外,每次調用“array.erase(itor);”,被刪除元素之后的內容會自動往前移,導致迭代漏項,應在刪除一項后使itor--,使之從已經前移的下一個元素起繼續遍歷。
int main(void) {typedef vector<int> IntArray;IntArray array;array.push_back( 1 );array.push_back( 2 );array.push_back( 2 );array.push_back( 3 );// 刪除array數組中所有的2for( IntArray::iterator itor=array.begin(); itor!=array.end(); ++itor ){if( 2 == *itor ){itor = array.erase( itor );itor--;}}return 0; }
14、
// 功能:由src所指內存區域復制count個字節到dest所指內存區域。 // 說明:src和dest所指內存區域可以重疊,但復制后dest內容會被更改。函數返回指向dest的指針 void *memmove(void *dest , const void *src , size_t count) {assert( (dest != NULL) && (src != NULL)); //安全檢查assert( count > 0 );char *psrc = (char *) src;char *pdest = (char *) dest;//檢查是否有重疊問題if( pdest < psrc ){//正向拷貝while( count-- )*pdest++ = *psrc++;}else if( psrc < pdest ){//反向拷貝psrc = psrc + count - 1;pdest = pdest + count - 1;while( count-- )*pdest-- = *psrc--;}return dest; }// 功能:由src指向地址為起始地址的連續n個字節的數據復制到以dest指向地址為起始地址的空間內。 // 說明:src和dest所指內存區域不能重疊,函數返回指向dest的指針 void *memmcpy(void *dest , const void *src , size_t count) {assert( (dest != NULL) && (src != NULL)); //安全檢查assert( count > 0 );char *psrc = (char *) src;char *pdest = (char *) dest;while( count-- )*pdest++ = *psrc++;return dest; }與50位技術專家面對面20年技術見證,附贈技術全景圖
總結
- 上一篇: 迅雷2012校园招聘笔试题
- 下一篇: N*N匹马,N个赛道,求出最快N匹马的解