歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

C++經典面試題

1,關於動態申請內存
 
答:內存分配方式三種:
 
(1)從靜態存儲區域分配:內存在程序編譯的時候就已經分配好,這塊內存在程序的整個運行期間都存在。
 
全局變量,static變量。
 
(2)在棧上創建:在執行函數時,函數內局部變量的存儲單元都可以在棧上創建,
 
函數執行結束時這些存儲單元自動被釋放。
 
棧內存分配運算內置於處理器的指令集中,效率很高,但是分配的內存容量有限。
 
(3)用malloc或new申請內存之後,應該立即檢查指針值是否為NULL.防止使用指針值為NULL的內存,
 
不要忘記為數組和動態內存賦初值。防止將未被初始化的內存作為右值使用。避免數組或指針的下標越界,
 
特別要當心發生“多1”或者“少1”操作。動態內存的申請與釋放必須配對,防止內存洩漏。
 
用free或delete釋放了內存之後,立即將指針設置為NULL,防止產生“野指針”。從堆上分配,亦稱動態內存分配。
 
程序在運行的時候用malloc或new申請任意多少的內存,程序員自己負責在何時用free或delete釋放內存。
 
動態內存的生存期由程序員決定,使用非常靈活。(int *pArray;  int MyArray[6];    pArray = &MyArray[0];)
 
如果在申請動態內存時找不到足夠大的內存塊,malloc和new將返回NULL指針,
 
判斷指針是否為NULL,如果是則馬上用return語句終止本函數,
 
或者馬上用exit(1)終止整個程序的運行,為new和malloc設置異常處理函數。
 
 
 
2,C++指針攻破
 
答案:指針是一個變量,專門存放內存地址,特點是能訪問所指向的內存
 
 
 
指針本身占據了4個字節的長度
 
int **ptr; //指針的類型是 int **
 
int (*ptr)[3]; //指針的類型是 int(*)[3]
 
int *(*ptr)[4]; //指針的類型是 int *(*)[4]
 
 ptr++:指針ptr的值加上了sizeof(int)
 
ptr+=5:將指針ptr的值加上5*sizeof(int)
 
 
 
指針的賦值:
 
把一個變量的地址賦予指向相同數據類型的指針變量( int a;  int *ip;  ip=&a; )
 
把一個指針變量的值賦予指向相同類型變量的另一個指針變量(int a;  int *pa=&a;  int *pb;  pb=pa; )
 
把數組的首地址賦予指向數組的指針變量(int a[5],*pa;  pa=a;  也可寫為:pa=&a[0];)
 
 
 
如果給指針加1或減1 ,實際上是加上或減去指針所指向的數據類型大小。
 
當給指針加上一個整數值或減去一個整數值時,表達式返回一個新地址。
 
相同類型的兩個指針可以相減,減後返回的整數代表兩個地址間該類型的實例個數。
 
 
 
int ** cc=new (int*)[10]; 聲明一個10個元素的數組,數組每個元素都是一個int *指針,
 
每個元素還可以單獨申請空間,因為cc的類型是int*型的指針,所以你要在堆裡申請的話就要用int *來申請;
 
  int ** a= new int * [2];     //申請兩個int * 型的空間
 
  a[0] = new int[4];        ////為a的第一個元素申請了4個int 型空間,a[0] 指向了此空間的首地址處
 
  a[1] = new int[3];        //為a的第二個元素又申請了3個int 型空間,a[1]指向了此空間首地址處
 
 
 
指針數組初始化賦值:
 
一維指針開辟空間:char *str;int *arr;    scanf("%d",&N);
 
str=(char*)malloc(sizeof(char)*N);
 
arr=(int*)malloc(sizeof(int)*N);
 
二維指針開辟空間:int **arr,      i;          scanf("%d%d",&row,&col);
 
arr=(int**)malloc(sizeof(int)*row);
 
for(i=0;i<row;i++)
 
  arr[i]=(int*)malloc(sizeof(int)*col);
 
 
 
結構體指針數組,例如typedef struct{  char x;  int  y; }Quan,*QQuan;
 
定義一個結構體指針數組如:QQuan a[MAX]
 
for(i=0;i<MAX;i++)
 
{
 
    a[i]=(QQuan)malloc(sizeof(Quan));
 
    memset(a[i],0,sizeof(Quan));
 
}
 
指針數組賦值
 
 float a[]={100,200,300,400,500};
 
float  *p[5]={&a[0],&a[1],&a[2],&a[3],&a[4]};
 
 
 
 
 
char *units[1000];
 
char get_unit[250];                                                                         
 
for(int i=0;i<get_unit_num;i++){ units[i]=(char*) malloc(60*sizeof(char*));
 
scanf("%s", get_unit);  strcpy(units[i],get_unit);}
 
 
 
 
 
3,復雜指針解析:
 
(1)int (*func)(int *p);
 
(*func)()是一個函數,func是一個指向這類函數的指針,就是一個函數指針,這類函數具有int*類型的形參,返回值類型是 int。
 
(2)int (*func)(int *p, int (*f)(int*));
 
func是一個指向函數的指針,這類函數具有int *和int (*)(int*)這樣的形參。形參int (*f)(int*),f也是一個函數指針
 
(3)int (*func[5])(int *p);
 
func數組的元素是函數類型的指針,它所指向的函數具有int*類型的形參,返回值類型為int。
 
(4)int (*(*func)[5])(int *p);
 
func是一個指向數組的指針,這個數組的元素是函數指針,這些指針指向具有int*形參,返回值為int類型的函數。
 
(5)int (*(*func)(int *p))[5];
 
func是一個函數指針,這類函數具有int*類型的形參,返回值是指向數組的指針,所指向的數組的元素是具有5個int元素的數組。
 
注意:
 
需要聲明一個復雜指針時,如果把整個聲明寫成上面所示的形式,對程序可讀性是一大損害。
 
應該用typedef來對聲明逐層,分解,增強可讀性,例如對於聲明:int (*(*func)(int *p))[5];
 
這樣分解:typedef  int (*PARA)[5];    typedef PARA (*func)(int *);
 
 
 
例如:int (*(*func)[5][6])[7][8];
 
  func是一個指向數組的指針,這類數組的元素是一個具有5X6個int元素的二維數組,而這個二維數組的元素又是一個二維數組。
 
  typedef int (*PARA)[7][8];
 
  typedef PARA (*func)[5][6];
 
例如:int (*(*(*func)(int *))[5])(int *);
 
  func是一個函數指針,這類函數的返回值是一個指向數組的指針,
 
所指向數組的元素也是函數指針,指向的函數具有int*形參,返回值為int。
 
  typedef int (*PARA1)(int*);
 
  typedef PARA1 (*PARA2)[5];
 
  typedef PARA2 (*func)(int*);
 
 
 
 
 
4,函數指針詳解
 
答:
 
函數指針是指向一個函數入口的指針
 
一個函數指針只能指向一種類型的函數,即具有相同的返回值和相同的參數的函數。
 
函數指針數組定義:void(*fun[3])(void*);  相應指向類A的成員函數的指針:void (A::*pmf)(char *, const char *);
 
指向外部函數的指針:void (*pf)(char *, const char *); void strcpy(char * dest, const char * source); pf=strcpy;
 
 
 
 
 
5,野指針
 
答:“野指針”是很危險的,if語句對它不起作用。“野指針”的成因主要有兩種:
 
(1)指針變量沒有被初始化。指針變量在創建的同時應當被初始化,要麼將指針設置為NULL,要麼讓它指向合法的內存。
 
char *p = NULL;      char *str = (char *) malloc(100);
 
(2)指針p被free或者delete之後,沒有置為NULL
 
(3)指針操作超越了變量的作用范圍。所指向的內存值對象生命期已經被銷毀
 
 
 
6,引用和指針有什麼區別?
 
答:引用必須初始化,指針則不必;引用初始化以後不能改變,指針可以改變其指向的對象;
 
不存在指向空值的引用,但存在指向控制的指針;
 
引用是某個對象的別名,主要用來描述函數和參數和返回值。而指針與一般的變量是一樣的,會在內存中開辟一塊內存。
 
如果函數的參數或返回值是類的對象的話,采用引用可以提高程序的效率。
 
 
 
7,C++中的Const用法
 
答:char * const p;    // 指針不可改,也就說指針只能指向一個地址,不能更改為其他地址,修飾指針本身
 
char const * p;  // 所指內容不可改,也就是說*p是常量字符串,修飾指針所指向的變量
 
const char * const p 和 char const * const p; // 內容和指針都不能改
 
 
 
const修飾函數參數是它最廣泛的一種用途,它表示函數體中不能修改參數的值,
 
傳遞過來的參數在函數內不可以改變,參數指針所指內容為常量不可變,參數指針本身為常量不可變
 
在引用或者指針參數的時候使用const限制是有意義的,而對於值傳遞的參數使用const則沒有意義
 
 
 
const修飾類對象表示該對象為常量對象,其中的任何成員都不能被修改。
 
const修飾的對象,該對象的任何非const成員函數都不能被調用,因為任何非const成員函數會有修改成員變量的企圖。
 
const修飾類的成員變量,表示成員常量,不能被修改,同時它只能在初始化列表中賦值。static const 的成員需在聲明的地方直接初始。
 
const修飾類的成員函數,則該成員函數不能修改類中任何非const成員。一般寫在函數的最後來修飾。
 
在函數實現部分也要帶const關鍵字.
 
對於const類對象/指針/引用,只能調用類���const成員函數,因此,const修飾成員函數的最重要作用就是限制對於const對象的使用
 
 
 
使用const的一些建議:在參數中使用const應該使用引用或指針,而不是一般的對象實例
 
const在成員函數中的三種用法(參數、返回值、函數)要很好的使用;
 
const在成員函數中的三種用法(參數、返回值、函數)要很好的使用;
 
不要輕易的將函數的返回值類型定為const;除了重載操作符外一般不要將返回值類型定為對某個對象的const引用;
Copyright © Linux教程網 All Rights Reserved