1.在C++ 程序中調(diào)用被C 編譯器編譯后的函數(shù),為什么要加extern “C”?
答:首先,extern是C/C++語言中表明函數(shù)和全局變量作用范圍的關(guān)鍵字,該關(guān)鍵字告訴編譯器,其聲明的函數(shù)和變量可以在本模塊或其它模塊中使用。
通常,在模塊的頭文件中對本模塊提供給其它模塊引用的函數(shù)和全局變量以關(guān)鍵字extern聲明。extern "C"是連接申明(linkage declaration),被extern "C"修飾的變量和函數(shù)是按照C語言方式編譯和連接的。作為一種面向?qū)ο蟮恼Z言,C++支持函數(shù)重載,而過程式語言C則不支持。函數(shù)被C++編譯后在符號 庫中的名字與C語言的不同。例如,假設(shè)某個函數(shù)的原型為:void foo( int x, int y );該函數(shù)被C編譯器編譯后在符號庫中的名字為_foo,而C++編譯器則會產(chǎn)生像_foo_int_int之類的名字。這樣的名字包含了函數(shù)名、函數(shù)參 數(shù)數(shù)量及類型信息,C++就是靠這種機制來實現(xiàn)函數(shù)重載的。
所以,可以用一句話概括extern “C”這個聲明的真實目的:解決名字匹配問題,實現(xiàn)C++與C的混合編程。
2.頭文件中的ifndef/define/endif有什么作用?
答:這是C++預(yù)編譯頭文件保護符,保證即使文件被多次包含,頭文件也只定義一次。
3.?#include 與 #include "file.h"的區(qū)別?
答:前者是從標(biāo)準(zhǔn)庫路徑尋找和引用file.h,而后者是從當(dāng)前工作路徑搜尋并引用file.h。
4.評價一下C/C++各自的特點
答:C語言是一種結(jié)構(gòu)化語言,面向過程,基于算法和數(shù)據(jù)結(jié)構(gòu),所考慮的是如何通過一個過程或者函數(shù)從輸入得到輸出;
C++是面向?qū)ο?,基于類、對象和繼承,所考慮的是如何構(gòu)造一個對象模型,讓這個模型能夠契合與之對應(yīng)的問題,通過獲取對象的狀態(tài)信息得到輸出或?qū)崿F(xiàn)過程控制。
5.const 有什么用途?
答:在C/C++中,(1)可以定義const常量,(2)修飾函數(shù)的返回值和形參;
在C++中,還可以修飾函數(shù)的定義體,定義類的const成員函數(shù)。被const修飾的東西受到強制保護,可以預(yù)防意外的變動,提高了程序的健壯性。
6.const和#define有什么區(qū)別?
答:(1)const和#define都可以定義常量,但是const用途更廣。
(2)const 常量有數(shù)據(jù)類型,而宏常量沒有數(shù)據(jù)類型。編譯器可以對前者進行類型安全檢查。而對后者只進行字符替換,沒有類型安全檢查,并且在字符替換可能會產(chǎn)生意料不到的錯誤。
(3) 有些集成化的調(diào)試工具可以對const 常量進行調(diào)試,但是不能對宏常量進行調(diào)試。
7.關(guān)于sizeof小結(jié)的。
答:sizeof計算的是在棧中分配的內(nèi)存大小。
(1) sizeof不計算static變量占得內(nèi)存;
(2) 指針的大小一定是4個字節(jié),而不管是什么類型的指針;
(3) char型占1個字節(jié),int占4個字節(jié),short int占2個字節(jié)
long int占4個字節(jié),float占4字節(jié),double占48字節(jié),string占4字節(jié)
一個空類占1個字節(jié),單一繼承的空類占1個字節(jié),虛繼承涉及到虛指針?biāo)哉?個字節(jié)
(4) 數(shù)組的長度:
若指定了數(shù)組長度,則不看元素個數(shù),總字節(jié)數(shù)=數(shù)組長度*sizeof(元素類型)
若沒有指定長度,則按實際元素個數(shù)類確定
Ps:若是字符數(shù)組,則應(yīng)考慮末尾的空字符。
(5) 結(jié)構(gòu)體對象的長度
在默認情況下,為方便對結(jié)構(gòu)體內(nèi)元素的訪問和管理,當(dāng)結(jié)構(gòu)體內(nèi)元素長度小于處理器位數(shù)的時候,便以結(jié)構(gòu)體內(nèi)最長的數(shù)據(jù)元素的長度為對齊單位,即為其整數(shù)倍。若結(jié)構(gòu)體內(nèi)元素長度大于處理器位數(shù)則以處理器位數(shù)為單位對齊。
(6) unsigned影響的只是最高位的意義,數(shù)據(jù)長度不會改變,所以sizeof(unsigned int)=4
(7) 自定義類型的sizeof取值等于它的類型原型取sizeof
(8) 對函數(shù)使用sizeof,在編譯階段會被函數(shù)的返回值的類型代替
(9) sizeof后如果是類型名則必須加括號,如果是變量名可以不加括號,這是因為sizeof是運算符
(10) 當(dāng)使用結(jié)構(gòu)類型或者變量時,sizeof返回實際的大小。當(dāng)使用靜態(tài)數(shù)組時返回數(shù)組的全部大小,sizeof不能返回動態(tài)數(shù)組或者外部數(shù)組的尺寸
8.sizeof與strlen的區(qū)別?
答: (1)sizeof的返回值類型為size_t(unsigned int);
(2)sizeof是運算符,而strlen是函數(shù);
(3)sizeof可以用類型做參數(shù),其參數(shù)可以是任意類型的或者是變量、函數(shù),而strlen只能用char*做參數(shù),且必須是以’\0’結(jié)尾;
(4)數(shù)組作sizeof的參數(shù)時不會退化為指針,而傳遞給strlen是就退化為指針;
(5)sizeof是編譯時的常量,而strlen要到運行時才會計算出來,且是字符串中字符的個數(shù)而不是內(nèi)存大?。?/p>
9.指針和引用的區(qū)別?
答:指針和引用都提供了間接操作對象的功能。
(1) 指針定義時可以不初始化,而引用在定義時就要初始化,和一個對象綁定,而且一經(jīng)綁定,只要引用存在,就會一直保持和該對象的綁定;
(2) 賦值行為的差異:指針賦值是將指針重新指向另外一個對象,而引用賦值則是修改對象本身;
(3) 指針之間存在類型轉(zhuǎn)換,而引用分const引用和非const應(yīng)用,非const引用只能和同類型的對象綁定,const引用可以綁定到不同但相關(guān)類型的對象或者右值
10.?dāng)?shù)組和指針的區(qū)別?
答:(1)數(shù)組要么在全局?jǐn)?shù)據(jù)區(qū)被創(chuàng)建,要么在棧上被創(chuàng)建;指針可以隨時指向任意類型的內(nèi)存塊;
(2)修改內(nèi)容上的差別:
char a[] = “hello”;
a[0] = ‘X’;
char *p = “world”; // 注意p 指向常量字符串
p[0] = ‘X’; // 編譯器不能發(fā)現(xiàn)該錯誤,運行時錯誤
(3)用運算符sizeof 可以計算出數(shù)組的容量(字節(jié)數(shù))。sizeof(p),p 為指針得到的是一個指針變量的字節(jié)數(shù),而不是p 所指的內(nèi)存容量。C++/C 語言沒有辦法知道指針?biāo)傅膬?nèi)存容量,除非在申請內(nèi)存時記住它。注意當(dāng)數(shù)組作為函數(shù)的參數(shù)進行傳遞時,該數(shù)組自動退化為同類型的指針。
11.空指針和懸垂指針的區(qū)別?
答:空指針是指被賦值為NULL的指針;delete指向動態(tài)分配對象的指針將會產(chǎn)生懸垂指針。
(1) 空指針可以被多次delete,而懸垂指針再次刪除時程序會變得非常不穩(wěn)定;
(2) 使用空指針和懸垂指針都是非法的,而且有可能造成程序崩潰,如果指針是空指針,盡管同樣是崩潰,但和懸垂指針相比是一種可預(yù)料的崩潰。
12.C++中有malloc/free,為什么還有new/delete?
答:malloc/free是C/C++標(biāo)準(zhǔn)庫函數(shù),new/delete是C++運算符。他們都可以用于動態(tài)申請和釋放內(nèi)存。
對于內(nèi)置類型數(shù)據(jù)而言,二者沒有多大區(qū)別。malloc申請內(nèi)存的時候要制定分配內(nèi)存的字節(jié)數(shù),而且不會做初始化;new申請的時候有默認的初始化,同時可以指定初始化;
對于類類型的對象而言,用malloc/free無法滿足要求的。對象在創(chuàng)建的時候要自動執(zhí)行構(gòu)造函數(shù),消亡之前要調(diào)用析構(gòu)函數(shù)。由于malloc /free是庫函數(shù)而不是運算符,不在編譯器控制之內(nèi),不能把執(zhí)行構(gòu)造函數(shù)和析構(gòu)函數(shù)的任務(wù)強加給它,因此,C++還需要new/delete。
13.什么是智能指針?
答:當(dāng)類中有指針成員時,一般有兩種方式來管理指針成員:一是采用值型的方式管理,每個類對象都保留一份指針指向的對象的拷貝;另一種更優(yōu)雅的方式是使用智能指針,從而實現(xiàn)指針指向的對象的共享。
智能指針的一種通用實現(xiàn)技術(shù)是使用引用計數(shù)。智能指針類將一個計數(shù)器與類指向的對象相關(guān)聯(lián),引用計數(shù)跟蹤該類有多少個對象共享同一指針。
每次創(chuàng)建類的新對象時,初始化指針并將引用計數(shù)置為1;當(dāng)對象作為另一對象的副本而創(chuàng)建時,拷貝構(gòu)造函數(shù)拷貝指針并增加與之相應(yīng)的引用計數(shù);對一個對 象進行賦值時,賦值操作符減少左操作數(shù)所指對象的引用計數(shù)(如果引用計數(shù)為減至0,則刪除對象),并增加右操作數(shù)所指對象的引用計數(shù);調(diào)用析構(gòu)函數(shù)時,構(gòu) 造函數(shù)減少引用計數(shù)(如果引用計數(shù)減至0,則刪除基礎(chǔ)對象)。
14.面向?qū)ο蠹夹g(shù)的基本概念是什么,三個基本特征是什么?
答:基本概念:類、對象、繼承; 基本特征:封裝、繼承、多態(tài)。
封裝:將低層次的元素組合起來形成新的、更高實體的技術(shù);
繼承:廣義的繼承有三種實現(xiàn)形式:實現(xiàn)繼承、可視繼承、接口繼承。
多態(tài):允許將子類類型的指針賦值給父類類型的指針
15.C++空類默認有哪些成員函數(shù)?
答:默認構(gòu)造函數(shù)、析構(gòu)函數(shù)、復(fù)制構(gòu)造函數(shù)、賦值函數(shù)
16.哪一種成員變量可以在一個類的實例之間共享?
答:static靜態(tài)成員變量
17.繼承層次中,為什么基類析構(gòu)函數(shù)是虛函數(shù)?
答:編譯器總是根據(jù)類型來調(diào)用類成員函數(shù)。但是一個派生類的指針可以安全地轉(zhuǎn)化為一個基類的指針。這樣刪除一個基類的指針的時候,C++不管這個指針指向 一個基類對象還是一個派生類的對象,調(diào)用的都是基類的析構(gòu)函數(shù)而不是派生類的。如果你依賴于派生類的析構(gòu)函數(shù)的代碼來釋放資源,而沒有重載析構(gòu)函數(shù),那么 會有資源泄漏。
18.為什么構(gòu)造函數(shù)不能為虛函數(shù)?
答:虛函數(shù)采用一種虛調(diào)用的方法。需調(diào)用是一種可以在只有部分信息的情況下工作的機制。如果創(chuàng)建一個對象,則需要知道對象的準(zhǔn)確類型,因此構(gòu)造函數(shù)不能為虛函數(shù)。
19.如果虛函數(shù)是有效的,那為什么不把所有函數(shù)設(shè)為虛函數(shù)?
答:不行。首先,虛函數(shù)是有代價的,由于每個虛函數(shù)的對象都要維護一個虛函數(shù)表,因此在使用虛函數(shù)的時候都會產(chǎn)生一定的系統(tǒng)開銷,這是沒有必要的。
20.構(gòu)造函數(shù)可以是內(nèi)聯(lián)函數(shù)
21.什么是多態(tài)?多態(tài)有什么作用?
答:多態(tài)就是將基類類型的指針或者引用指向派生類型的對象。多態(tài)通過虛函數(shù)機制實現(xiàn)。
多態(tài)的作用是接口重用。
22.重載和覆蓋有什么區(qū)別?
答:虛函數(shù)是基類希望派生類重新定義的函數(shù),派生類重新定義基類虛函數(shù)的做法叫做覆蓋;
重載就在允許在相同作用域中存在多個同名的函數(shù),這些函數(shù)的參數(shù)表不同。重載的概念不屬于面向?qū)ο缶幊?,編譯器根據(jù)函數(shù)不同的形參表對同名函數(shù)的名稱做修飾,然后這些同名函數(shù)就成了不同的函數(shù)。
重載的確定是在編譯時確定,是靜態(tài)的;虛函數(shù)則是在運行時動態(tài)確定。
23.公有繼承、受保護繼承、私有繼承
答:(1)公有繼承時,派生類對象可以訪問基類中的公有成員,派生類的成員函數(shù)可以訪問基類中的公有和受保護成員;
(2)私有繼承時,基類的成員只能被直接派生類的成員訪問,無法再往下繼承;
(3)受保護繼承時,基類的成員也只被直接派生類的成員訪問,無法再往下繼承。
24.公有繼承時基類受保護的成員,可以通過派生類對象訪問但不能修改。
25.有哪幾種情況只能用構(gòu)造函數(shù)初始化列表而不能用賦值初始化?
答:const成員,引用成員
26.什么是虛指針?
答:虛指針或虛函數(shù)指針是虛函數(shù)的實現(xiàn)細節(jié)。帶有虛函數(shù)的每一個對象都有一個虛指針指向該類的虛函數(shù)表。
27.C++如何阻止一個類被實例化?一般在什么時候?qū)?gòu)造函數(shù)聲明為private?
答:(1)將類定義為抽象基類或者將構(gòu)造函數(shù)聲明為private;
(2)不允許類外部創(chuàng)建類對象,只能在類內(nèi)部創(chuàng)建對象
28.main函數(shù)執(zhí)行之前會執(zhí)行什么?執(zhí)行之后還能執(zhí)行代碼嗎?
答:(1)全局對象的構(gòu)造函數(shù)會在main函數(shù)之前執(zhí)行;
(2)可以,可以用_onexit 注冊一個函數(shù),它會在main 之后執(zhí)行;
如果你需要加入一段在main退出后執(zhí)行的代碼,可以使用atexit()函數(shù),注冊一個函數(shù)。
語法:
#include
#include
int atexit(void (*function")(void));
void fn1( void ), fn2( void ), fn3( void );
int main( void )
{
atexit(fn1);
atexit( fn2 );
printf( "This is executed first.\n" );
}
void fn1()
{
printf( " This is\n" );
}
void fn2()
{
printf( " executed next." );
}
結(jié)果:
This is executed first.
This is executed next.
29.請描述進程和線程的區(qū)別?
答:(1)進程是程序的一次執(zhí)行,線程是進程中的執(zhí)行單元;
(2)進程間是獨立的,這表現(xiàn)在內(nèi)存空間、上下文環(huán)境上,線程運行在進程中;
(3)一般來講,進程無法突破進程邊界存取其他進程內(nèi)的存儲空間;而同一進程所產(chǎn)生的線程共享內(nèi)存空間;
(4)同一進程中的兩段代碼不能同時執(zhí)行,除非引入多線程。
30.進程間如何通信?
答:信號、信號量、消息隊列、共享內(nèi)存
31.在網(wǎng)絡(luò)編程中涉及并發(fā)服務(wù)器,使用多進程與多線程的區(qū)別?
答:(1)線程執(zhí)行開銷小,但不利于資源管理和保護;進程則相反,進程可跨越機器遷移。
(2)多進程時每個進程都有自己的內(nèi)存空間,而多線程間共享內(nèi)存空間;
(3)線程產(chǎn)生的速度快,線程間通信快、切換快;
(4)線程的資源利用率比較好;
(5)線程使用公共變量或者資源時需要同步機制。
32.說一下TCP 3次握手、4次揮手的全過程。
33.TCP和UDP有什么區(qū)別。
答:
TCP——傳輸控制協(xié)議,提供的是面向連接、可靠的字節(jié)流服務(wù)。
當(dāng)客戶和服務(wù)器彼此交換數(shù)據(jù)前,必須先在雙方之間建立一個TCP連接,之后才能傳輸數(shù)據(jù)。TCP提供超時重發(fā),丟棄重復(fù)數(shù)據(jù),檢驗數(shù)據(jù),流量控制等功能,保證數(shù)據(jù)能從一端傳到另一端。
UDP——用戶數(shù)據(jù)報協(xié)議,是一個簡單的面向數(shù)據(jù)報的傳輸層協(xié)議。UDP不提供可靠性,它只是把應(yīng)用程序傳給IP層的數(shù)據(jù)報發(fā)送出去,但是并不能保證它們 能到達目的地。由于UDP在傳輸數(shù)據(jù)報前不用在客戶和服務(wù)器之間建立一個連接,且沒有超時重發(fā)等機制,故而傳輸速度很快.
TCP協(xié)議和UDP協(xié)議的一些特性區(qū)別如下:
1.TCP協(xié)議在傳送數(shù)據(jù)段的時候要給段標(biāo)號;UDP 協(xié)議不需要。
2.TCP協(xié)議可靠;UDP協(xié)議不可靠。
3.TCP協(xié)議是面向連接;UDP協(xié)議采用無連接。
4.TCP協(xié)議負載較高,采用虛電路;UDP協(xié)議低負載。
5.TCP協(xié)議的發(fā)送方要確認接受方是否收到數(shù)據(jù)段(3次握手協(xié)議)。
6.TCP協(xié)議采用窗口技術(shù)和流控制。
34.如何編寫套接字?
35.調(diào)用函數(shù)時要進行參數(shù)壓棧,一般情況下順序是從最右邊參數(shù)往左壓棧。
36.經(jīng)常要操作的內(nèi)存分為那幾個類別?
答:(1)棧區(qū):由編譯器自動分配和釋放,存放函數(shù)的參數(shù)值、局部變量的值等;
(2)堆:一般由程序員分配和釋放,存放動態(tài)分配的變量;(new/delete;malloc/free)
(3)全局區(qū)(靜態(tài)區(qū)):全局變量和靜態(tài)變量存放在這一塊,初始化的和未初始化的分開放;
(4)文字常量區(qū):常量字符串就放在這里,程序結(jié)束自動釋放;
(5)程序代碼區(qū):參訪函數(shù)體的二進制代碼。
37.請講述堆和棧的區(qū)別。
答:(1)申請方式不同。棧上有系統(tǒng)自動分配和釋放;堆上有程序員自己申請并指明大??;
(2)棧是向低地址擴展的數(shù)據(jù)結(jié)構(gòu),大小很有限;堆是向高地址擴展,是不連續(xù)的內(nèi)存區(qū)域,空間相對大且靈活;
(3)棧由系統(tǒng)分配和釋放速度快;堆由程序員控制,一般較慢,且容易產(chǎn)生碎片;
38.全局變量放在數(shù)據(jù)段,內(nèi)部變量static int count;放在數(shù)據(jù)段,內(nèi)部變量char *p=“AAA”,p的位置在堆棧上,指向的空間的位置數(shù)據(jù)段,內(nèi)部變量char *p=new char;p的位置堆,指向的空間的位置數(shù)據(jù)段
39.字符數(shù)組與字符串的比較:最明顯的區(qū)別是字符串會在末尾自動添加空字符。
41.類使用static成員的優(yōu)點,如何訪問?
答:優(yōu)點:
(1)static 成員的名字是在類的作用域中,因此可以避免與其他類的成員或全局對象名字沖突;
(2)可以實施封裝。static 成員可以是私有成員,而全局對象不可以;
(3) static 成員是與特定類關(guān)聯(lián)的,可清晰地顯示程序員的意圖。
static 數(shù)據(jù)成員必須在類定義體的外部定義(正好一次),static 關(guān)鍵字只能用于類定義體內(nèi)部的聲明中,定義不能標(biāo)示為static. 不像普通數(shù)據(jù)成員,static成員不是通過類構(gòu)造函數(shù)進行初始化,也不能在類的聲明中初始化,而是應(yīng)該在定義時進行初始化.保證對象正好定義一次的最好 辦法,就是將static 數(shù)據(jù)成員的定義放在包含類非內(nèi)聯(lián)成員函數(shù)定義的文件中。
靜態(tài)數(shù)據(jù)成員初始化的格式為:
<數(shù)據(jù)類型><類名>::<靜態(tài)數(shù)據(jù)成員名>=<值>
類的靜態(tài)數(shù)據(jù)成員有兩種訪問形式:
<類對象名>.<靜態(tài)數(shù)據(jù)成員名> 或 <類類型名>::<靜態(tài)數(shù)據(jù)成員名>
42. static數(shù)據(jù)成員和static成員函數(shù)
答:(1)static數(shù)據(jù)成員:
static數(shù)據(jù)成員獨立于該類的任意對象而存在;每個static數(shù)據(jù)成員是與類關(guān)聯(lián)的對象,并不與該類的對象相關(guān)聯(lián)。Static數(shù)據(jù)成員 (const static數(shù)據(jù)成員除外)必須在類定義體的外部定義。不像普通數(shù)據(jù)成員,static成員不是通過類的構(gòu)造函數(shù)進行初始化,而是應(yīng)該在定義時進行初始 化。
(2)static成員函數(shù):
Static成員函數(shù)沒有this形參,它可以直接訪問所屬類的static成員,不能直接使用非static成員。因為static成員不是任何對象的組成部分,所以static成員不能被聲明為const。同時,static成員函數(shù)也不能被聲明為虛函數(shù)。
43.static成員變量定義放在cpp文件中,不能放在初始化列表中。Const static成員可就地初始化。
44.如何引用一個已經(jīng)定義過的全局變量?
答:可以用引用頭文件的方式,也可以用extern關(guān)鍵字,如果用引用頭文件方式來引用某個在頭文件中聲明的全局變量,假定你將那個變量寫錯了,那么在編譯期間會報錯,如果你用extern方式引用時,假定你犯了同樣的錯誤,那么在編譯期間不會報錯,而在連接期間報錯。
44.static關(guān)鍵字的作用。
答:static總是使得變量或?qū)ο蟮拇鎯π问阶兂伸o態(tài)存儲,連接方式變成內(nèi)部連接,對于局部變量(已經(jīng)是內(nèi)部連接了),它僅改變其存儲方式;對于全局變量(已經(jīng)是靜態(tài)存儲了),它僅改變其連接類型。
47.多態(tài)類中的虛函數(shù)表是 Compile-Time,還是 Run-Time時建立的?
答案:虛擬函數(shù)表是在編譯期就建立了,各個虛擬函數(shù)這時被組織成了一個虛擬函數(shù)的入口地址的數(shù)組。而對象的隱藏成員--虛擬函數(shù)表指針是在運行期--也就是構(gòu)造函數(shù)被調(diào)用時進行初始化的,這是實現(xiàn)多態(tài)的關(guān)鍵。
48.?一個父類寫了一個 virtual?函數(shù),如果子類覆蓋它的函數(shù)不加 virtual ,也能實現(xiàn)多態(tài)?
在子類的空間里,有沒有父類的這個函數(shù),或者父類的私有變量? (華為筆試題)
答案:只要基類在定義成員函數(shù)時已經(jīng)聲明了 virtue關(guān)鍵字,在派生類實現(xiàn)的時候覆蓋該函數(shù)時,virtue關(guān)鍵字可加可不加,不影響多態(tài)的實現(xiàn)。子類的空間里有父類的所有變量(static除外)。
49. 完成字符串拷貝可以使用 sprintf、strcpy 及 memcpy 函數(shù),請問這些函數(shù)有什么區(qū)別
,你喜歡使用哪個,為什么?
答案:這些函數(shù)的區(qū)別在于 實現(xiàn)功能以及操作對象不同。
(1)strcpy 函數(shù)操作的對象是字符串,完成從源字符串到目的字符串的拷貝功能。
(2)sprintf 函數(shù)操作的對象不限于字符串:雖然目的對象是字符串,但是源對象可以是字符串、也可以是任意基本類型的數(shù)據(jù)。這個函數(shù)主要用來實現(xiàn)(字符串或基本數(shù)據(jù)類型)向字符串的轉(zhuǎn)換功能。如果源對象是字符串,并且指定 %s 格式符,也可實現(xiàn)字符串拷貝功能。
(3)memcpy 函數(shù)顧名思義就是內(nèi)存拷貝,實現(xiàn)將一個內(nèi)存塊的內(nèi)容復(fù)制到另一個內(nèi)存塊這一功能。內(nèi)存塊由其首地址以及長度確定。程序中出現(xiàn)的實體對象,不論是什么類型, 其最終表現(xiàn)就是在內(nèi)存中占據(jù)一席之地(一個內(nèi)存區(qū)間或塊)。因此,memcpy 的操作對象不局限于某一類數(shù)據(jù)類型,或者說可適用于任意數(shù)據(jù)類型,只要能給出對象的起始地址和內(nèi)存長度信息、并且對象具有可操作性即可。鑒于memcpy 函數(shù)等長拷貝的特點以及數(shù)據(jù)類型代表的物理意義,memcpy 函數(shù)通常限于同種類型數(shù)據(jù)或?qū)ο笾g的拷貝,其中當(dāng)然也包括字符串拷貝以及基本數(shù)據(jù)類型的拷貝。
對于字符串拷貝來說,用上述三個函數(shù)都可以實現(xiàn),但是其實現(xiàn)的效率和使用的方便程度不同:
? strcpy 無疑是最合適的選擇:效率高且調(diào)用方便。
? sprintf 要額外指定格式符并且進行格式轉(zhuǎn)化,麻煩且效率不高。
? memcpy 雖然高效,但是需要額外提供拷貝的內(nèi)存長度這一參數(shù),易錯且使用不便;并且如果長度指定過大的話(最優(yōu)長度是源字符串長度 + 1),還會帶來性能的下降。其實 strcpy 函數(shù)一般是在內(nèi)部調(diào)用 memcpy 函數(shù)或者用匯編直接實現(xiàn)的,以達到高效的目的。因此,使用 memcpy 和 strcpy 拷貝字符串在性能上應(yīng)該沒有什么大的差別。
對于非字符串類型的數(shù)據(jù)的復(fù)制來說,strcpy 和 snprintf 一般就無能為力了,可是對 memcpy 卻沒有什么影響。但是,對于基本數(shù)據(jù)類型來說,盡管可以用 memcpy 進行拷貝,由于有賦值運算符可以方便且高效地進行同種或兼容類型的數(shù)據(jù)之間的拷貝,所以這種情況下 memcpy 幾乎不被使用 。memcpy 的長處是用來實現(xiàn)(通常是內(nèi)部實現(xiàn)居多)對結(jié)構(gòu)或者數(shù)組的拷貝,其目的是或者高效,或者使用方便,甚或兩者兼有。
50. 應(yīng)用程序在運行時的內(nèi)存包括代碼區(qū)和數(shù)據(jù)區(qū),其中數(shù)據(jù)區(qū)又包括哪些部分?
答:對于一個進程的內(nèi)存空間而言,可以在邏輯上分成 3個部份:代碼區(qū),靜態(tài)數(shù)據(jù)區(qū)和動態(tài)數(shù)據(jù)區(qū)。
動態(tài)數(shù)據(jù)區(qū)一般就是“堆棧”。 棧是一種線性結(jié)構(gòu),堆是一種鏈?zhǔn)浇Y(jié)構(gòu)。進程的每個線程都有私有的“棧”。
全局變量和靜態(tài)變量分配在靜態(tài)數(shù)據(jù)區(qū),本地變量分配在動態(tài)數(shù)據(jù)區(qū),即堆棧中。程序通過堆棧的基地址和偏移量來訪問本地變量。
51. C++函數(shù)中值的傳遞方式有哪幾種?
答:三種傳遞方式為:值傳遞、指針傳遞和引用傳遞。
52. C++里面是不是所有的動作都是main()引起的?如果不是,請舉例.
比如全局變量的初始化,就不是由main函數(shù)引起的
舉例: class A{};
A a; //a的構(gòu)造函數(shù)執(zhí)行
int main() {}
54. 內(nèi)聯(lián)函數(shù)在編譯時是否做參數(shù)類型檢查?
答:內(nèi)聯(lián)函數(shù)要做參數(shù)類型檢查, 這是內(nèi)聯(lián)函數(shù)跟宏相比的優(yōu)勢。
55. 全局變量和局部變量有什么區(qū)別?實怎么實現(xiàn)的?操作系統(tǒng)和編譯器是怎么知道的?
(1)生命周期不同:
全局變量隨主程序創(chuàng)建和創(chuàng)建,隨主程序銷毀而銷毀
局部變量在局部函數(shù)內(nèi)部,甚至局部循環(huán)體等內(nèi)部存在,退出就不存在; 內(nèi)存中
分配在全局?jǐn)?shù)據(jù)區(qū)
(2)使用方式不同:通過聲明后全局變量程序的各個部分都可以用到;局部變量只能在局部使用,分配在棧區(qū)
操作系統(tǒng)和編譯器通過內(nèi)存分配的位置來知道的,全局變量分配在全局?jǐn)?shù)據(jù)段并且在程序開始運行的時候被加載。局部變量則分配在堆棧里面 。
57.static全局變量與普通的全局變量有什么區(qū)別?static局部變量和普通局部變量有什么區(qū)別?static函數(shù)與普通函數(shù)有什么區(qū)別?
答:static全局變量與普通全局變量區(qū)別:static全局變量只初使化一次,防止在其他文件單元中被引用;
static局部變量和普通局部變量區(qū)別:static局部變量只被初始化一次,下一次依據(jù)上一次結(jié)果值;
static函數(shù)與普通函數(shù)區(qū)別:static函數(shù)在內(nèi)存中只有一份,普通函數(shù)在每個被調(diào)用中維持一份拷貝。
58.?程序的局部變量存在于(堆棧)中,全局變量存在于(靜態(tài)區(qū)?)中,動態(tài)申請數(shù)據(jù)存在于(?堆)中。
59.?對于一個頻繁使用的短小函數(shù),在C語言中應(yīng)用什么實現(xiàn),在C++中應(yīng)用什么實現(xiàn)?
c用宏定義,c++用inline