C++面试题一
指針指向一塊內存,它的內容是指向內存的地址;引用是某內存的別名
引用使用是無需解引用,指針需解引用
引用不能為空,指針可以為空
引用在定義是被初始化一次,之后不可變;指針可變
程序為指針變量分配內存區域,而引用不需要分配內存區域
memcpy用來內存拷貝的,它有指定的拷貝數據長度,他可以拷貝任何數據類型的對象
Strcpy它只能去拷貝字符串,它遇到’\0′結束拷貝
malloc與free是C++/C語言的標準庫函數,new/delete是C++的運算符。它們都可用于申請動態內存和釋放內存。
對于非內部數據類型的對象而言,光用maloc/free無法滿足動態對象的要求。對象在創建的同時要自動執行構造函數,對象在消亡之前要自動執行析構函數。由于malloc/free是庫函數而不是運算符,不在編譯器控制權限之內,不能夠把執行構造函數和析構函數的任務強加于malloc/free。
因此C++語言需要一個能完成動態內存分配和初始化工作的運算符new,以及一個能完成清理與釋放內存工作的運算符delete。注意new/delete不是庫函數。
1.成員變量
結構在默認情況下的成員是公共(public)的,
而類在默認情況下的成員是私有(private)的。
2.存儲
struct保證成員按照聲明順序在內存中存儲。class不保證等等
3.繼承
struct A { };
class B : A{ }; //private繼承
struct C : B{ }; //public繼承
這是由于class默認是private,struct默認是public。
1.一個union類型的變量,所有成員變量共享一塊內存,該內存的大小有這些成員變量中長度最大的一個來決定,struct中成員變量內存都是獨立的
2.union分配的內存是連續的,而struct不能保證分配的內存是連續的
隊列先進先出,棧后進先出
16位機????????2字節
32位機????????4字節
64位機????????8字節
extern
可以用引用頭文件的方式,也可以用extern關鍵字,如果用引用頭文件方式來引用某個在頭文件中聲明的全局變理,假定你將那個變寫錯了,那么在編譯期間會報錯,如果你用extern方式引用時,假定你犯了同樣的錯誤,那么在編譯期間不會報錯,而在連接期間報錯
可以,在不同的C文件中以static形式來聲明同名全局變量。
可以在不同的C文件中聲明同名的全局變量,前提是其中只能有一個C文件中對此變量賦初值,此時連接不會出錯
for( ;1 ;)和while(1)相同。
前一個循環一遍再判斷,后一個判斷以后再循環
#include<stdio.h>
main()
{
int a,b,c,d;
a=10;
b=a++;
c=++a;
d=10*a++;
printf(“b,c,d:%d,%d,%d”,b,c,d);
return 0;
}
10,12,120
c用宏定義,c++用inline
全局對象的構造函數會在main 函數之前執行。
可以,可以用on_exit 注冊一個函數,它會在main 之后執行int fn1(void), fn2(void), fn3(void), fn4 (void);
void main( void )
{
String str(“zhanglin”);
on_exit( fn1 );
on_exit( fn2 );
on_exit( fn3 );
on_exit( fn4 );
printf( “This is executed first.\n” );
}
int fn1()
{
printf( “next.\n” );
return 0;
}
int fn2()
{
printf( “executed ” );
return 0;
}
int fn3()
{
printf( “is ” );
return 0;
}
int fn4()
{
printf( “This ” );
return 0;
}
The on_exit function is passed the address of a function (func) to be called when the program terminates normally. Successive calls to on_exit create a register of functions that are executed in LIFO (last-in-first-out) order. The functions passed to on_exit cannot take parameters.
This is executed next.
能,局部會屏蔽全局。要用全局變量,需要使用”::”
局部變量可以與全局變量同名,在函數內引用這個變量時,會用到同名的局部變量,而不會用到全局變量。對于有些編譯器而言,在同一個函數內可以定義多個同名的局部變量,比如在兩個循環體內都定義一個同名的局部變量,而那個局部變量的作用域就在那個循環體內
1.從靜態存儲區域分配。內存在程序編譯的時候就已經分配好,這塊內存在程序的整個運行期間都存在。例如全局變量,static 變量。
2. 在棧上創建。在執行函數時,函數內局部變量的存儲單元都可以在棧上創建,函數執行結束時這些存儲單元自動被釋放。棧內存分配運算內置于處理器的指令集。
3. 從堆上分配,亦稱動態內存分配。程序在運行的時候用malloc 或new 申請任意多少的內存,程序員自己負責在何時用free 或delete 釋放內存。動態內存的生存期由程序員決定,使用非常靈活,但問題也最多。
1.成員函數被重載的特征:
(1)相同的范圍(在同一個類中);
(2)函數名字相同;
(3)參數不同;
(4)virtual 關鍵字可有可無。
2.覆蓋是指派生類函數覆蓋基類函數,特征是:
(1)不同的范圍(分別位于派生類與基類);
(2)函數名字相同;
(3)參數相同;
(4)基類函數必須有virtual 關鍵字。
3.”隱藏”是指派生類的函數屏蔽了與其同名的基類函數,規則如下:
(1)如果派生類的函數與基類的函數同名,但是參數不同。此時,不論有無virtual關鍵字,基類的函數將被隱藏(注意別與重載混淆)。
(2)如果派生類的函數與基類的函數同名,并且參數也相同,但是基類函數沒有virtual 關鍵字。此時,基類的函數被隱藏(注意別與覆蓋混淆)
1.限制變量的作用域
2.設置變量的存儲域
1.const 常量有數據類型,而宏常量沒有數據類型。編譯器可以對前者進行類型安全檢查。而對后者只進行字符替換,沒有類型安全檢查,并且在字符替換可能會產生意料不到的錯誤。
2.有些集成化的調試工具可以對const 常量進行調試,但是不能對宏常量進行調試。
堆棧溢出一般是由什么原因導致的?
沒有回收垃圾資源
?
數組要么在靜態存儲區被創建(如全局數組),要么在棧上被創建。指針可以隨時指向任意類型的內存塊。
(1)修改內容上的差別
char a[] = “hello”;
a[0] = ‘X’;
char *p = “world”; // 注意p 指向常量字符串
p[0] = ‘X’; // 編譯器不能發現該錯誤,運行時錯誤
(2) 用運算符sizeof 可以計算出數組的容量(字節數)。sizeof(p),p 為指針得到的是一個指針變量的字節數,而不是p 所指的內存容量。C++/C 語言沒有辦法知道指針所指的內存容量,除非在申請內存時記住它。注意當數組作為函數的參數進行傳遞時,該數組自動退化為同類型的指針。
char a[] = “hello world”;
char *p = a;
cout<< sizeof(a) << endl; // 12 字節
cout<< sizeof(p) << endl; // 4 字節
計算數組和指針的內存容量
void Func(char a[100])
{
cout<< sizeof(a) << endl; // 4 字節而不是100 字節
}
( ( a + b ) + abs( a – b ) ) / 2
O(n^2)
構造函數(Constructor)
全局變量????????????????????全局靜態區
全局靜態變量????????????????全局靜態區
全局常量
????????有初始化????????????代碼區
????????無初始化????????????全局靜態區
局部變量????????????????????堆棧區
局部靜態變量????????????????靜態區
局部常量????????????????????堆棧區
????new和malloc分配空間????堆區
管道(有名管道,無名管道),共享內存,消息隊列,信號量,socket通信
臨界區:通過對多線程的串行化來訪問公共資源或一段代碼,速度快,適合控制數據訪問
互斥量:為協調共同對一個共享資源的單獨訪問而設計
信號量(PV操作):為控制一個具有有限數量用戶資源而設計
事件:用來通知線程有一些事件已
資源:進程是擁有資源的一個獨立單位,線程是不擁有資源。
調度:線程作為調度和分配的基本單位,進程是作為資源的基本單位
并發性:進程之間可以有并發性進行,同一個進程中的多個線程是可以并發執行
系統開銷:進程在創建和撤銷的時候,由于系統要分配和回收資源,導致系統的開銷明顯大于線程
一個進程可以擁有多個線程。
能,局部屏蔽全局。在C++里使用全局,需要使用”::”。在C語言里,extern
虛函數必須實現,純虛函數沒有實現
虛函數在子類里可以不重載,但是純虛函數必須在每一個子類里去實現
在動態內存分配的時候,析構函數必須是虛函數,但沒有必要是純虛函數
封裝、繼承、多態(抽象)
封裝:把客觀事物封裝成抽象的類,并且類可以把自己的數據和方法只讓可信的類或者對象操作,對不可信的進行信息隱藏
繼承:子類可以擁有父類的屬性和方法,但父類沒有子類的屬性和方法
多態:允許將子類類型的指針賦值給父類類型的指針
實現多態,有二種方式,覆蓋,重載
覆蓋,是指子類重新定義父類的虛函數的做法
重載,是指允許存在多個同名函數,而這些函數的參數表不同(或許參數個數不同,或許參數類型不同,或許兩者都不同)
vi +5000 filename
2個字節
兩個指針指向鏈表頭,一個指針每次走一步,另一個指針每次走兩步,若有一個指針先指向為NULL表示這個鏈表無環。若兩個指針重合表示鏈表有環
換行刷新緩沖區
printf(“\n”);
使用函數刷新緩沖區
fflush(stdout);
程序結束刷新緩沖區
return 0;
對象就是對客觀事物在計算機中的抽象描述。
類就是對具體相似屬性和行為的一組對象的統一描述。
類的包括:類說明和類實現兩大部分:
類說明提供了對該類所有數據成員和成員函數的描述。
類實現提供了所有成員函數的實現代碼。
第一范式:沒有重復的列
第二范式:非主屬的部分依賴于主屬部分
第三范式:屬性部分不依賴于其他非主屬部分
是在調試程序使用的一個宏,括號里面要滿足,如果不滿足,程序將報告錯誤,并將終止執行。
用內存映射或全局原子(互斥變量)、查找窗口句柄
FindWindow,互斥,寫標志到文件或注冊表,共享內存
鍵盤鉤子SetWindowsHookEx
總結
- 上一篇: Undo/Redo框架实现
- 下一篇: 开发者都应该使用的10个C++11特性