C++筆試易錯題集(持續更新)


1.如下代碼輸出結果是什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include<stdio.h>
char *myString()
{
    char buffer[6] = {0};
    char *s = "Hello World!";
    for (int i = 0; i < sizeof(buffer) - 1; i++)
    {
        buffer[i] = *(s + i);
    }
    return buffer;
}
int main(int argc, char **argv)
{
    printf("%s\n", myString());
    return 0;
}
  • Hello
  • Hello World!
  • Well
  • 以上全部不正確

解析:

答案:D

函數char *myString()中沒有使用new或者malloc分配內存,所有buffer數組的內存區域在棧區

隨着char *myString()的結束,棧區內存釋放,字符數組也就不存在了,所以會產生野指針,輸出結果未知 

 


 

2.

1
2
3
4
5
6
7
enum string{    
    x1,    
    x2,    
    x3=10,    
    x4,    
    x5,    
} x;
問x等於什么?(0)
在c語言中,這樣寫法一般是全局變量,程序初始化時會清零.

3.
設已經有A,B,C,D4個類的定義,程序中A,B,C,D析構函數調用順序為?
1
2
3
4
5
6
7
8
C c;
void main()
{
    A*pa=new A();
    B b;
    static D d;
    delete pa;
}
 
A B C D
A B D C(正確)
A C D B
A C B D
解析:
這道題主要考察的知識點是 :全局變量,靜態局部變量,局部變量空間的堆分配和棧分配
其中全局變量和靜態局部變量時從 靜態存儲區中划分的空間,
二者的區別在於作用域的不同,全局變量作用域大於靜態局部變量(只用於聲明它的函數中),
而之所以是先釋放 D 在釋放 C的原因是, 程序中首先調用的是 C的構造函數,然后調用的是 D 的構造函數,析構函數的調用與構造函數的調用順序剛好相反。
局部變量A 是通過 new 從系統的堆空間中分配的,程序運行結束之后,系統是不會自動回收分配給它的空間的,需要程序員手動調用 delete 來釋放。
局部變量 B 對象的空間來自於系統的棧空間,在該方法執行結束就會由系統自動通過調用析構方法將其空間釋放。
之所以是 先 A  后 B 是因為,B 是在函數執行到 結尾 "}" 的時候才調用析構函數, 而語句 delete a ; 位於函數結尾 "}" 之前。

4.若char是一字節,int是4字節,指針類型是4字節,代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
class CTest
{
    public:
        CTest():m_chData(‘\0’),m_nData(0)
        {
        }
        virtual void mem_fun(){}
    private:
        char m_chData;
        int m_nData;
        static char s_chData;
};
char CTest::s_chData=’\0’;
問:
(1)若按4字節對齊sizeof(CTest)的值是多少(12)?
(2)若按1字節對齊sizeof(CTest)的值是多少(9)?
請選擇正確的答案。
解析:
答案分別是:12 和 9,對應C
考察點:c++ 類的內存布局。
上精華圖:一張圖說明類中成員變量,成員函數,靜態變量與函數的空間位置。
 
 
理論如上,下面就是代碼運行后真是執行結果。無pp無真相。這是4字節對齊,結果是12= 4(虛表指針)+1(char )+3(對齊補位)+4(int)
 
 
 
 
以下是1字節對齊,結果是9 =4(虛表指針)+1(char )+4(int):
 

 
5.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include<iostream>
using namespace std;
class MyClass
{
public:
    MyClass(int i = 0)
    {
        cout << i;
    }
    MyClass(const MyClass &x)
    {
        cout << 2;
    }
    MyClass &operator=(const MyClass &x)
    {
        cout << 3;
        return *this;
    }
    ~MyClass()
    {
        cout << 4;
    }
};
int main()
{
    MyClass obj1(1), obj2(2);
    MyClass obj3 = obj1;
    return 0;
}
運行時的輸出結果是()
  • 11214444
  • 11314444
  • 122444(正確)
  • 123444
解析:首先程序中存在三個MyClass對象。
前兩個對象構造時分別輸出1,2
第三個對象是這樣構造的MyClass obj3 = obj1;這里會調用拷貝構造函數,輸出2
然后三個對象依次析構,輸出444
所以最終輸出122444  MyClass obj3 = obj1;這里調用拷貝構造函數,如果是在這之前obj3,obj1都已聲明,則此時調用的是coby assignment操作符

 


6. 當參數*x==1, *y==1, *z==1時,下列不可能是函數add的返回值的( )?
1
2
3
4
5
6
int add(int *x, int *y, int *z){
    *x += *x;
    *y += *x;
    *z += *y;
    return *z;
 }
  • 4
  • 5
  • 6
  • 7
 解析:
D
開始不知道啥意思,后經牛客網的大神指點才知道這題要考慮的是,x,y,z三個參數是否指向同一地址(或者說調用該函數時是否實參相同),如:當a=b=c=1時,add(&a,&a,&a),add(&a,&b,&c)。
通過寫程序測試得出結果,不可能得到答案7。
有以下5種情況
 

7. SQL語言集數據查詢、數據操縱、數據定義和數據控制功能於一體,語句INSERT、DELETE、UPDATE實現( )功能。
  • 數據查詢
  • 數據控制
  • 數據定義
  • 數據操縱
 D
解析:
DDL:數據庫模式定義語言,關鍵字:create
DML:數據操縱語言,關鍵字:Insert、delete、update
DCL:數據庫控制語言 ,關鍵字:grant、remove
DQL:數據庫查詢語言,關鍵字:select

 8. 觀察下面一段代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class ClassA
{
public:
    virtual ~ ClassA(){};
    virtual void FunctionA(){};
};
class ClassB
{
public:
   virtual void FunctionB(){};
};
class ClassC : public ClassA,public ClassB
{
    public:
};
  
ClassC aObject;
ClassA* pA=&aObject;
ClassB* pB=&aObject;
ClassC* pC=&aObject;
關於pA,pB,pC的取值,下面的描述中正確的是:
  • pA,pB,pC的取值相同.
  • pC=pA+pB
  • pA和pB不相同
  • pC不等於pA也不等於pB
 解析:
如果我們輸出三個指針的值。
上面的代碼在我的電腦上輸出
0x7fff502f5aa80x7fff502f5ab00x7fff502f5aa8
 
可以看到pA和pC是相同的。
所以選擇C。
 
實際上,在這個情況下,子類的指針和第一個基類的指針應該是一樣的,和第二個基類是不一樣的。
 
9. 連續整數之和為1000的共有幾組?(m,n都為正整數)
  • 3
  • 4
  • 5
  • 8
答案:B
設從n加到m和為1000,則(n+m)(m-n+1)/2=1000,即(n+m)(m-n+1)=2000,即把2000分解成兩個數的乘積,且這兩個數為一奇一偶。2000=(2^4)*(5^3),於是奇數可能為5^0,5^1,5^2,5^3,即有四組解

10.
一個有序數列,序列中的每一個值都能夠被2或者3或者5所整除,這個序列的初始值從1開始,但是1並不在這個數列中。求第1500個值是多少?
  • 2040
  • 2042
  • 2045
  • 2050
答案:C
2、3、5的最小公倍數是30。[ 1, 30]內符合條件的數有22個。如果能看出[ 31, 60]內也有22個符合條件的數,那問題就容易解決了。也就是說,這些數具有周期性,且周期為30.
第1500個數是:1500/22=68   1500%68=4。也就是說:第1500個數相當於經過了68個周期,然后再取下一個周期內的第4個數。一個周期內的前4個數:2,3,4,5。
故,結果為68*30=2040+5=2045

11.一個完全二叉樹有770個節點,那么其葉子的個數為 :_____
解析:對於一個完全二叉樹 如果總結點數為偶數,則度為1的結點數為1,如果總結點數為奇數且大於1,則度為1的結點數為0;本題總結點數我770為偶數,所以度為1的結點數n1 = 1;度為0的結點數與度為2的結點數:n0 = n2 + 1;所以總結點數:n0+n1+n2 = 2n0 - 1 + 1 = 770,所以n0 = 385,即葉子結點的個數

12.計算三個稠密矩陣 A、B、C 的乘積 ABC,假定三個矩陣的尺寸分別為 m*n, n*p,p*q,且 m<n<p<q,以下計算效率最高的是
    • (AB)C
    • A(BC)
    • (AC)B
    • (BC)A
    • (CA)B
 
解析:a*b,b*c兩矩陣相乘效率為a*c*b ABC=(AB)C=A(BC).(AB)C = m*n*p + m*p*q,A(BC)=n*p*q + m*n*q.m*n*p<m*n*q,m*p*q<n*p*q,所以(AB)C最小

13.通過算法生成的隨機數是“偽隨機”的,也就是說,在設定好第一個數之后,后面的數字的序列是確定的,並且經過一個非常大的循環會回到第一個數的狀態,然后周而復始。顯然,搖號、抽獎的程序是不能通過偽隨機數來實現的。現實中常常基於某種熱噪聲來實現真正的隨機數。假定某熱噪聲是標准正態分布,那么能否將它轉換成(0,1)區間上的均勻分布______?
  • 忽略測量和計算誤差,可以轉換為(0,1)區間上的均勻分布
  • 無法轉換為(0,1)區間上的均勻分布
  • 信息不足,無法判斷
  • 借助偽隨機數生成算法可以轉換為(0,1)區間上的均勻分布
  • 僅僅靠偽隨機數生成算法,就可以生成(0,1)區間上的均勻分布
  • 以上說法都不對
 解析:http://www.zhihu.com/question/25111423

14.二分查找樹里查詢一個關鍵字的最壞時間復雜度是______
  • O(n)
  • O(n log n)
  • O(n^2)
  • O(n^3)
  • O(logn)
  • 不確定
解析:最壞的情況就是這個二分查找樹的所有節點只有左子樹或者只有右子樹,就相當於一個線性鏈表,所以是O(n)

15.下列 C 代碼中,不屬於未定義行為的有:______。
  • int i=0;i=(i++);
  • char *p=”hello”;p[1]=’E’
  • char *p=”hello”;char ch=*p++
  • int i=0;printf(“%d%d\n”,i++ i--)
  • 都是未定義行為
  • 都不是未定義行為
解析:C

16.C++內存分配中說法錯誤的是:______。
  • 對於棧來講,生長方向是向上的,也就是向着內存地址增加的方向
  • 對於堆,大量的 new/delete 操作會造成內存空間的不連續
  • 堆容易產生 memory leak D,堆的效率比棧要低的多
  • 堆的效率比棧要低得多
  • 棧變量引用容易逃逸
  • 以上都對
解析:堆的生長方向向上,棧的生長方向向下17.在小端序的機器中,如果 
1
2
3
4
union X{
    int x;
    char y[4];
};
如果:
X a;
a.x=0x11223344;//16 進制 則:______
    • a.y[0]=11
    • a.y[1]=11
    • a.y[2]=11
    • a.y[3]=11
    • a.y[0]=22
    • a.y[3]=22
解析:小端是數據低字節存儲在內存低位,所以y[0]=0x44,y[3] = 0x1118.下面的排序算法中,初始數據集的排列順序對算法的性能無影響的是
  • 插入排序
  • 堆排序
  • 冒泡排序
  • 快速排序
解析:
B,堆排序
有影響就是這個排序算法最好情況和最差情況的時間復雜度不同。對於無影響,我們只要找最好情況和最差情況時間復雜度一樣的算法就可以了,
根據各種排序算法的流程,對於插入排序,如果幾乎有序的話,每個節點的初始位置就最終位置,所以幾乎不需要移動節點。
對於冒泡排序,如果節點幾乎有序的話,對於一次遍歷設置標記為,如果不交換元素的話即結束排序過程。
對於快速排序,如果以初始序列是逆序的話,時間復雜度變為n^2.
綜上,時間堆排序的最差和最優時間復雜度都為nlogn,所以堆排序是最優的,還有歸並排序對元素的初始位置也不敏感,都是nlogn。

19.下列的進程狀態變化中,哪些是不可能發生的?
  • 運行→就緒
  • 運行→等待
  • 等待→運行
  • 等待→就緒
解析:選C ,就緒狀態是可以和運行狀態相互轉換的,超時的時候就會從運行狀態轉為就緒狀態。但是一旦是等待狀態(阻塞)就必須選轉為就緒才能夠運行。

20.使用 char* p = new char[100]申請一段內存,然后使用delete p釋放,有什么問題?
  • 會有內存泄露
  • 不會有內存泄露,但不建議用
  • 編譯就會報錯,必須使用delete []p;
  • 編譯沒問題,運行會直接崩潰
解析:the answer is B ,  if the type is int,char,float, both delete[]p and delete p are ok,but if the type is class object, the answer will be A
 

 21.x為整型,請用位運算實現x%8解析:
當我們求余的時候,相當於除以2的N次冥,也就是相當於把數本身右移N位,但是右移掉的那些位需要通過位運算進行保留;用以上例子來說,X%8即X%2^3,那么就需要右移三次,那么移去的三位需要保留下來,而8=1000,剛好,可以使用0111來保留下來后三位,於是,對於除數都是2的整數次冪的情況,可以使用x & (2^n-1)的方法進行與運算,保留下來的最末尾的n位就是余數。
該題中,結果為x&7.

 


免責聲明!

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



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