C++面試題(四)

const相關:
1.總結const的應用和作用?
答:(1)欲阻止一個變量被改變,可以使用const關鍵字。在定義該const變量時,通常需要對它進行初始化,因爲以後就沒有機會再去改變它了;
(2)對指針來說,可以指定指針本身爲const,也可以指定指針所指的數據爲const,或二者同時指定爲const;
(3)在一個函數聲明中,const可以修飾形參,表明它是一個輸入參數,在函數內部不能改變其值;
(4)對於類的成員函數,若指定其爲const類型,則表明其是一個常函數,不能修改類的成員變量;
(5)對於類的成員函數,有時候必須指定其返回值爲const類型,以使得其返回值不爲“左值”。
2.說明define和const在語法和含義上有什麼不同?
答:(1) #define是C語法中定義符號變量的方法,符號常量只是用來表達一個值,在編譯階段符號就被值替換了,它沒有類型;
(2) Const是C++語法中定義常變量的方法,常變量具有變量特性,它具有類型,內存中存在以它命名的存儲單元,可以用sizeof測出長度
3.const 符號常量;
(1)const char *p
(2)char const *p
(3)char * const p
說明上面三種描述的區別 .
答:如果 const 位於星號的左側,則 const 就是用來修飾指針所指向的變量,即指針指向爲常量;
如果 const 位於星號的右側, const 就是修飾指針本身,即指針本身是常量。
(1)const char *p
一個指向 char 類型的 const 對象指針, p 不是常量 , 我們可以修改 p 的值,使其指向不同的 char ,但是不能改變它指向非 char 對象,如:
const char *p;
char c1=’a’;
char c2=’b’;
p=&c1;//ok
p=&c2;//ok
*p=c1;//error
(3)char * const p
此時 *p 可以修改,而 p 不能修改。
(4)const char * const
這種是地址及指向對象都不能修改。
4.const 有什麼用途?(請至少說明兩種)
答:(1)可以定義 const 常量,(2)const 可以修飾函數的參數、返回值,甚至函數的定義體。被const 修飾的東西都受到強制保護,可以預防意外的變動,能提高程序的健壯性。

static相關:
總結static的應用和作用?
答:(1)函數體內static變量的作用範圍爲該函數體,不同於auto變量,該變量的內存只被分配一次,因此其值在下次調用時仍維持上次的值;
(2)在模塊內的static全局變量可以被模塊內所用函數訪問,但不能被模塊外其它函數訪問;
(3)在模塊內的static函數只可被這一模塊內的其它函數調用,這個函數的使用範圍被限制在聲明它的模塊內;
(4)在類中的static成員變量屬於整個類所擁有,對類的所有對象只有一份拷貝;
(5)在類中的static成員函數屬於整個類所擁有,這個函數不接收this指針,因而只能訪問類的static成員變量。

聯合。結構體,類相關
1、設有以下說明和定義:

typedef union  {    
    long i;  
    int k[5];
    char c;  
} DATE;    
struct data  {   
    int cat; 
    DATE cow;    
    double dog; 
} too;     

則語句 printf(“%d”,sizeof(struct data)+sizeof(max));的執行結果是:52
考點:區別struct與union.(一般假定在32位機器上)
答:DATE是一個union, 變量公用空間. 裏面最大的變量類型是int[5], 佔用20個字節. 所以它的大小是20. data是一個struct, 每個變量分開佔用空間. 依次爲int4 + DATE20 + double8 = 32. 所以結果是 20 + 32 = 52. 當然…在某些16位編輯器下, int可能是2字節,那麼結果是 int2 + DATE10 + double8 = 20

struct(結構) 和 union(聯合)的區別?
1)結構和聯合都是由多個不同的數據類型成員組成, 但在任何同一時刻, 聯合中只存放了一個被選中的成員(所有成員共用一塊地址空間), 而結構的所有成員都存在(不同成員的存放地址不同)。
2) 對於聯合的不同成員賦值, 將會對其它成員重寫, 原來成員的值就不存在了, 而對於結構的不同成員賦值是互不影響的。

class 和 struct 的區別?
答:struct 的成員默認是公有的,而類的成員默認是私有的
結構體在默認情況下的成員都是public的,而類在默認情況下的成員是private的。結構體和類都必須使用new創建,
struct保證成員按照聲明順序在內存在存儲,而類不保證。

下面關於“聯合”的題目的輸出?
a)

#include
union
{
    int i;
    char x[2];
}a;
void main()
{
    a.x[0] = 10;
    a.x[1] = 1;
    printf(“%d”,a.i);
}
//答案:266 (低位低地址,高位高地址,內存佔用情況是Ox010A)

b)

main()
{
    union{
        int i;
        struct{
            char first;
            char second;
        }half;
    }number;
    number.i=0×4241;
    printf(“%c%c ”, number.half.first, mumber.half.second);
    number.half.first=’a';
    number.half.second=’b';
    printf(“%x ”, number.i);
    getch();
}
//答案: AB (0×41對應’A',是低位;Ox42對應’B',是高位)
//6261 (number.i和number.half共用一塊地址空間)

關聯、聚合(Aggregation)以及組合(Composition)的區別?
涉及到UML中的一些概念:關聯是表示兩個類的一般性聯繫,比如“學生”和“老師”就是一種關聯關係;聚合表示has-a的關係,是一種相對鬆散的關係,聚合類不需要對被聚合類負責,如下圖所示,用空的菱形表示聚合關係:
從實現的角度講,聚合可以表示爲:
class A {…} class B { A* a; …..}
而組合表示contains-a的關係,關聯性強於聚合:組合類與被組合類有相同的生命週期,組合類要對被組合類負責,採用實心的菱形表示組合關係:
實現的形式是:
class A{…} class B{ A a; …}

class MyStruct{   
    double ddal;    
    char dda;    
    int type;
}

在VC中測試上面結構的大小時,你會發現sizeof(MyStruct)爲16。
其實,這是VC對變量存儲的一個特殊處理。爲了提高CPU的存儲速度,VC對一些變量的起始地址做了“對齊”處理。在默認情況下,VC規定各成員變量存放的起始地址相對於結構的始地址偏移量必須爲該變量的類型佔用字節數的倍數,如Char偏移量爲sizeof(char)即1的倍數,先爲第一個成員dda1分配空間,其起始地址跟結構的起始地址相同,偏移量0剛好爲sizeof(double)的倍數,該成員變量佔用sizeof(double)=8個字節;接下來爲第二個成員dda分配空間,這時下一個可以分配的地址對於結構的起始地址的偏移量爲8,是sizeof(char)的倍數,佔sizeof(char)=1字節爲第三個成員type分配空間,這時下一個可以分配的地址對於結構的起始地址的偏移量爲9,不是sizeof(int)=4的倍數,爲了滿足對齊方式對偏移量的約束問題,VC自動填充3個字節
這時下一個可以分配的地址對於結構的起始地址的偏移量是12,剛好是sizeof(int)=4的倍數,
所以把type存放在偏移量爲12的地方,佔 用sizeof(int)=4個字節。總的佔用的空間大小爲:8+1+3+4=16,剛好爲結構的字節邊界數(即結構中佔用最大空間的類型所佔用的字節數sizeof(double)=8)的倍數,所以沒有空缺的字節需要填充。

sizeof()相關:
記住一點,C++無法知道指針所指對象的大小,指針的大小永遠爲4字節

char a[]=”Hello World!”
char *p=a;
count sizeof(a) end; //12字節
count sizeof(p) endl; //4字節
char s1[] = ""    //1
char *q = NULL    //4
void *r = malloc(100)  //4

//strlen函數
char s1[10] = {'m',o'','b','i','l'}
char s2[20] = {'A','N','S','I','\0','C','+','+'}
char s3[6] = {'I','D','O','C','+','+'}
//strlen(s1) = 5
//strlen(s2) = 4
//strlen(s3) = 不確定
//s2[8] = ‘\0’

而且,在函數中,數組參數退化爲指針,所以下面的內容永遠輸出爲4

void fun(char a[1000])
{
count sizeof(a) endl; //輸出4而不是1000
}

以下爲Windows NT 下的32 位C++程序,請計算sizeof 的值(10 分)

void Func ( char str[100])
{
    //請計算
    sizeof( str ) = 42 分)
}
char str[] = “Hello” ;
char *p = str ;
int n = 10;
//請計算
sizeof (str ) = 62 分)
sizeof ( p ) = 42 分)
sizeof ( n ) = 42 分)
void *p = malloc( 100 );
//請計算
sizeof ( p ) = 42 分)

引用相關:
1.引用和指針有什麼區別?
答:引用必須初始化,指針則不必;引用初始化以後不能改變,指針可以改變其指向的對象;
不存在指向空值的引用,但存在指向控制的指針;
引用是某個對象的別名,主要用來描述函數和參數和返回值。而指針與一般的變量是一樣的,會在內存中開闢一塊內存。
如果函數的參數或返回值是類的對象的話,採用引用可以提高程序的效率。

2.將“引用”作爲函數參數有哪些特點
答:(1)傳遞引用給函數與傳遞指針的效果是一樣的,這時,被調函數的形參就成爲原來主調函數的實參變量或者
對象的一個別名來使用,所以在被調函數中形參的操作就是對相應的目標對象的操作
(2)使用引用傳遞函數的參數,在內存中並沒有產生實參的副本,它是直接對實參操作,當參數數據較大時,引用
傳遞參數的效率和所佔空間都好
(3)如果使用指針要分配內存單元,需要重複使用“*指針變量名”形式進行計算,容易出錯且閱讀性較差。

各類零值比較:
分別寫出BOOL,int, float, 指針類型的變量 a 與 “零值”的比較語句

  BOOL: if(!aor   if(a)
  int : if( 0 == a)
  float : const EXPRESSION EXP = 0.000001;
  if(a < EXP && a > -EXP)
  pointer:     if(a != NULL) or  if(a == NULL)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章