1. 程式人生 > >面試2(C/C++試題彙總(微軟))

面試2(C/C++試題彙總(微軟))

1.求下面函式的返回值(微軟)

int func(x)
{
        int countx = 0;
        while(x)
        {
              countx ++;
              x = x&(x-1);
         }
        return countx;
}  

假定x = 9999。 答案:8

思路:將x轉化為2進位制,看含有的1的個數。

2. 什麼是“引用”?申明和使用“引用”要注意哪些問題?

答:引用就是某個目標變數的“別名”(alias),對引用的操作與對變數直接操作效果完全相同。申明一個引用的時候,切記要對其進行初始化

。引用宣告完畢後,相當於目標變數名有兩個名稱,即該目標原名稱和引用名,不能再把該引用名作為其他變數名的別名。宣告一個引用,不是新定義了一個變數,它只表 示該引用名是目標變數名的一個別名,它本身不是一種資料型別,因此引用本身不佔儲存單元,系統也不給引用分配儲存單元。不能建立陣列的引用。

3. 將“引用”作為函式引數有哪些特點?

(1)傳遞引用給函式與傳遞指標的效果是一樣的。這時,被調函式的形參就成為原來主調函式中的實參變數或物件的一個別名來使用,所以在被調函式中對形參變數的操作就是對其相應的目標物件(在主調函式中)的操作。

(2)使用引用傳遞函式的引數,在記憶體中並沒有產生實參的副本,它是直接對實參操作;而使用一般變數傳遞函式的引數,當發生函式呼叫時,需要給形參 分配儲存單元,形參變數是實參變數的副本;如果傳遞的是物件,還將呼叫拷貝建構函式。因此,當引數傳遞的資料較大時,用引用比用一般變數傳遞引數的效率和 所佔空間都好。

(3)使用指標作為函式的引數雖然也能達到與使用引用的效果,但是,在被調函式中同樣要給形參分配儲存單元,且需要重複使用"*指標變數名"的形式 進行運算,這很容易產生錯誤且程式的閱讀性較差;另一方面,在主調函式的呼叫點處,必須用變數的地址作為實參。而引用更容易使用,更清晰。

4. 在什麼時候需要使用“常引用”? 

如果既要利用引用提高程式的效率,又要保護傳遞給函式的資料不在函式中被改變,就應使用常引用。常引用宣告方式:const 型別識別符號 &引用名=目標變數名;

例1

int a ;
const int &ra=a;
ra=1; //錯誤
a=1; //正確

例2

string foo( );
void bar(string & s);

那麼下面的表示式將是非法的:

bar(foo( ));
bar("hello world");

原因在於foo( )和"hello world"串都會產生一個臨時物件,而在C++中,這些臨時物件都是const型別的。因此上面的表示式就是試圖將一個const型別的物件轉換為非const型別,這是非法的。

引用型引數應該在能被定義為const的情況下,儘量定義為const 。

5. 將“引用”作為函式返回值型別的格式、好處和需要遵守的規則?

格式:型別識別符號 &函式名(形參列表及型別說明){ //函式體 }

好處:在記憶體中不產生被返回值的副本;(注意:正是因為這點原因,所以返回一個區域性變數的引用是不可取的。因為隨著該區域性變數生存期的結束,相應的引用也會失效,產生runtime error!

注意事項:

1)不能返回區域性變數的引用。這條可以參照Effective C++[1]的Item 31。主要原因是區域性變數會在函式返回後被銷燬,因此被返回的引用就成為了"無所指"的引用,程式會進入未知狀態。

2)不能返回函式內部new分配的記憶體的引用。這條可以參照Effective C++[1]的Item 31。雖然不存在區域性變數的被動銷燬問題,可對於這種情況(返回函式內部new分配記憶體的引用),又面臨其它尷尬局面。例如,被函式返回的引用只是作為一 個臨時變量出現,而沒有被賦予一個實際的變數,那麼這個引用所指向的空間(由new分配)就無法釋放,造成memory leak。

3)可以返回類成員的引用,但最好是const。這條原則可以參照Effective C++[1]的Item 30。主要原因是當物件的屬性是與某種業務規則(business rule)相關聯的時候,其賦值常常與某些其它屬性或者物件的狀態有關,因此有必要將賦值操作封裝在一個業務規則當中。如果其它物件可以獲得該屬性的非常 量引用(或指標),那麼對該屬性的單純賦值就會破壞業務規則的完整性。

4)流操作符過載返回值申明為“引用”的作用:

流操作符<<和>>,這兩個操作符常常希望被連續使用,例如:cout << "hello" << endl; 因此這兩個操作符的返回值應該是一個仍然支援這兩個操作符的流引用。可選的其它方案包括:返回一個流物件和返回一個流物件指標。但是對於返回 一個流物件,程式必須重新(拷貝)構造一個新的流物件,也就是說,連續的兩個<<操作符實際上是針對不同物件的!這無法讓人接受。對於返回一 個流指標則不能連續使用<<操作符。因此,返回一個流物件引用是惟一選擇。這個唯一選擇很關鍵,它說明了引用的重要性以及無可替代性,也許這 就是C++語言中引入引用這個概念的原因吧。 賦值操作符=。這個操作符象流操作符一樣,是可以連續使用的,例如:x = j = 10;或者(x=10)=100;賦值操作符的返回值必須是一個左值,以便可以被繼續賦值。因此引用成了這個操作符的惟一返回值選擇。

例3

#i nclude <iostream.h>
int &put(int n);
int vals[10];
int error=-1;
void main()
{
put(0)=10; //以put(0)函式值作為左值,等價於vals[0]=10;
put(9)=20; //以put(9)函式值作為左值,等價於vals[9]=20;
cout<<vals[0];
cout<<vals[9];
}
int &put(int n)
{
if (n>=0 && n<=9 ) return vals[n];
else { cout<<"subscript error"; return error; }
}

5)在另外的一些操作符中,卻千萬不能返回引用:+-*/ 四則運算子。它們不能返回引用,Effective C++[1]的Item23詳細的討論了這個問題。主要原因是這四個操作符沒有side effect,因此,它們必須構造一個物件作為返回值,可選的方案包括:返回一個物件、返回一個區域性變數的引用,返回一個new分配的物件的引用、返回一 個靜態物件引用。根據前面提到的引用作為返回值的三個規則,第2、3兩個方案都被否決了。靜態物件的引用又因為((a+b) == (c+d))會永遠為true而導致錯誤。所以可選的只剩下返回一個物件了。

6. “引用”與多型的關係?

引用是除指標外另一個可以產生多型效果的手段。這意味著,一個基類的引用可以指向它的派生類例項。

例4

Class A; Class B : Class A{...};      B b; A& ref = b;

7. “引用”與指標的區別是什麼?

指標通過某個指標變數指向一個物件後,對它所指向的變數間接操作。程式中使用指標,程式的可讀性差;而引用本身就是目標變數的別名,對引用的操作就是對目標變數的操作。此外,就是上面提到的對函式傳ref和pointer的區別。

8. 什麼時候需要“引用”?

流操作符<<和>>、賦值操作符=的返回值、拷貝建構函式的引數、賦值操作符=的引數、其它情況都推薦使用引用。

以上 2-8 參考:http://hi.baidu.com/zhanghaooy/blog/item/ff801c3f8da77bca7d1e7120.html

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

10. 下面關於“聯合”的題目的輸出?

a)

#i nclude <stdio.h>
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=0x4241;             /*聯合成員賦值*/
              printf("%c%c/n", number.half.first, mumber.half.second);
              number.half.first='a';       /*聯合中結構成員賦值*/
              number.half.second='b';
              printf("%x/n", number.i);
              getch();
         }
答案: AB       (0x41對應'A',是低位;Ox42對應'B',是高位)

           6261 (number.i和number.half共用一塊地址空間)

11. 已知strcpy的函式原型:char *strcpy(char *strDest, const char *strSrc)其中strDest 是目的字串,strSrc 是源字串。不呼叫C++/C 的字串庫函式,請編寫函式 strcpy。


答案:
char *strcpy(char *strDest, const char *strSrc)
{
if ( strDest == NULL || strSrc == NULL)
return NULL ;
if ( strDest == strSrc)
return strDest ;
char *tempptr = strDest ;
while( (*strDest++ = *strSrc++) != ‘/0’)
;
return tempptr ;
}

12. 已知String類定義如下:

class String
{
public:
String(const char *str = NULL); // 通用建構函式
String(const String &another); // 拷貝建構函式
~ String(); // 解構函式
String & operater =(const String &rhs); // 賦值函式
private:
char *m_data; // 用於儲存字串
};

嘗試寫出類的成員函式實現。

答案:

String::String(const char *str)
{
       if ( str == NULL ) //strlen在引數為NULL時會拋異常才會有這步判斷
         {
           m_data = new char[1] ;
           m_data[0] = '/0' ;
         }
       else
        {
           m_data = new char[strlen(str) + 1];
           strcpy(m_data,str);
        }

}

String::String(const String &another)
{
        m_data = new char[strlen(another.m_data) + 1];
        strcpy(m_data,other.m_data);
}


String& String::operator =(const String &rhs)
{
        if ( this == &rhs)
            return *this ;
        delete []m_data; //刪除原來的資料,新開一塊記憶體
        m_data = new char[strlen(rhs.m_data) + 1];
        strcpy(m_data,rhs.m_data);
        return *this ;
}


String::~String()
{
        delete []m_data ;
}

13. .h標頭檔案中的ifndef/define/endif 的作用?

答:防止該標頭檔案被重複引用。

14. #i nclude<file.h> 與 #i nclude "file.h"的區別?

答:#include <filename.h> 引用標準庫的標頭檔案(從標準庫目錄開始搜尋) 直接從庫中查詢
#include “filename.h” 引用非標準庫的標頭檔案(從使用者工作目錄開始搜尋)先在當前位置查詢,如果沒有找到在從庫中查詢

15.在C++ 程式中呼叫被C 編譯器編譯後的函式,為什麼要加extern “C”?

首先,作為extern是C/C++語言中表明函式和全域性變數作用範圍(可見性)的關鍵字,該關鍵字告訴編譯器,其宣告的函式和變數可以在本模組或其它模組中使用。

通常,在模組的標頭檔案中對本模組提供給其它模組引用的函式和全域性變數以關鍵字extern宣告。例如,如果模組B欲引用該模組A中定義的全域性變數和 函式時只需包含模組A的標頭檔案即可。這樣,模組B中呼叫模組A中的函式時,在編譯階段,模組B雖然找不到該函式,但是並不會報錯;它會在連線階段中從模組 A編譯生成的目的碼中找到此函式

extern "C"是連線申明(linkage declaration),被extern "C"修飾的變數和函式是按照C語言方式編譯和連線的,來看看C++中對類似C的函式是怎樣編譯的:

作為一種面向物件的語言,C++支援函式過載,而過程式語言C則不支援。函式被C++編譯後在符號庫中的名字與C語言的不同。例如,假設某個函式的原型為:

void foo( int x, int y );

該函式被C編譯器編譯後在符號庫中的名字為_foo,而C++編譯器則會產生像_foo_int_int之類的名字(不同的編譯器可能生成的名字不同,但是都採用了相同的機制,生成的新名字稱為“mangled name”)。

_foo_int_int這樣的名字包含了函式名、函式引數數量及型別資訊,C++就是靠這種機制來實現函式過載的。例如,在C++中,函式 void foo( int x, int y )與void foo( int x, float y )編譯生成的符號是不相同的,後者為_foo_int_float。

同樣地,C++中的變數除支援區域性變數外,還支援類成員變數和全域性變數。使用者所編寫程式的類成員變數可能與全域性變數同名,我們以"."來區分。而本 質上,編譯器在進行編譯時,與函式的處理相似,也為類中的變數取了一個獨一無二的名字,這個名字與使用者程式中同名的全域性變數名字不同。

未加extern "C"宣告時的連線方式

假設在C++中,模組A的標頭檔案如下:

// 模組A標頭檔案 moduleA.h
#ifndef MODULE_A_H
#define MODULE_A_H
int foo( int x, int y );
#endif  

在模組B中引用該函式:

// 模組B實現檔案 moduleB.cpp
#i nclude "moduleA.h"
foo(2,3);

實際上,在連線階段,聯結器會從模組A生成的目標檔案moduleA.obj中尋找_foo_int_int這樣的符號!

加extern "C"聲明後的編譯和連線方式

加extern "C"聲明後,模組A的標頭檔案變為:

// 模組A標頭檔案 moduleA.h
#ifndef MODULE_A_H
#define MODULE_A_H
extern "C" int foo( int x, int y );
#endif  

在模組B的實現檔案中仍然呼叫foo( 2,3 ),其結果是:
(1)模組A編譯生成foo的目的碼時,沒有對其名字進行特殊處理,採用了C語言的方式;

(2)聯結器在為模組B的目的碼尋找foo(2,3)呼叫時,尋找的是未經修改的符號名_foo。

如果在模組A中函式聲明瞭foo為extern "C"型別,而模組B中包含的是extern int foo( int x, int y ) ,則模組B找不到模組A中的函式;反之亦然。

所以,可以用一句話概括extern “C”這個宣告的真實目的(任何語言中的任何語法特性的誕生都不是隨意而為的,來源於真實世界的需求驅動。我們在思考問題時,不能只停留在這個語言是怎麼 做的,還要問一問它為什麼要這麼做,動機是什麼,這樣我們可以更深入地理解許多問題):實現C++與C及其它語言的混合程式設計。  

明白了C++中extern "C"的設立動機,我們下面來具體分析extern "C"通常的使用技巧:

extern "C"的慣用法

(1)在C++中引用C語言中的函式和變數,在包含C語言標頭檔案(假設為cExample.h)時,需進行下列處理:

extern "C"
{
#i nclude "cExample.h"
}

而在C語言的標頭檔案中,對其外部函式只能指定為extern型別,C語言中不支援extern "C"宣告,在.c檔案中包含了extern "C"時會出現編譯語法錯誤。

C++引用C函式例子工程中包含的三個檔案的原始碼如下:

/* c語言標頭檔案:cExample.h */
#ifndef C_EXAMPLE_H
#define C_EXAMPLE_H
extern int add(int x,int y);
#endif


/* c語言實現檔案:cExample.c */
#i nclude "cExample.h"
int add( int x, int y )
{
return x + y;
}


// c++實現檔案,呼叫add:cppFile.cpp
extern "C"
{
#i nclude "cExample.h"
}
int main(int argc, char* argv[])
{
add(2,3);
return 0;
}

如果C++呼叫一個C語言編寫的.DLL時,當包括.DLL的標頭檔案或宣告介面函式時,應加extern "C" { }。


(2)在C中引用C++語言中的函式和變數時,C++的標頭檔案需新增extern "C",但是在C語言中不能直接引用聲明瞭extern "C"的該標頭檔案,應該僅將C檔案中將C++中定義的extern "C"函式宣告為extern型別。

C引用C++函式例子工程中包含的三個檔案的原始碼如下:

//C++標頭檔案 cppExample.h
#ifndef CPP_EXAMPLE_H
#define CPP_EXAMPLE_H
extern "C" int add( int x, int y );
#endif


//C++實現檔案 cppExample.cpp
#i nclude "cppExample.h"
int add( int x, int y )
{
return x + y;
}


/* C實現檔案 cFile.c
/* 這樣會編譯出錯:#i nclude "cExample.h" */
extern int add( int x, int y );
int main( int argc, char* argv[] )
{
add( 2, 3 );
return 0;
}

15題目的解答請參考《C++中extern “C”含義深層探索》註解:


16. 關聯、聚合(Aggregation)以及組合(Composition)的區別?

涉及到UML中的一些概念:關聯是表示兩個類的一般性聯絡,比如“學生”和“老師”就是一種關聯關係;聚合表示has-a的關係,是一種相對鬆散的關係,聚合類不需要對被聚合類負責,如下圖所示,用空的菱形表示聚合關係:

從實現的角度講,聚合可以表示為:

class A {...}      class B { A* a; .....}

而組合表示contains-a的關係,關聯性強於聚合:組合類與被組合類有相同的生命週期,組合類要對被組合類負責,採用實心的菱形表示組合關係:

實現的形式是:

class A{...} class B{ A a; ...}

防止該標頭檔案被重複引用如果標頭檔案被重複引用了,根據檔案的內容有不同的後果,比如重複定義。

例:可以用來預防多重包含同一標頭檔案
#ifndef SALESITEM_H
#define SALESITEM_H
#endif
#ifndef指示檢測預SALESITEM_H處理器變數是否未定義,如果未定義
,
那麼後面所有的指示全被處理直到出現#endif

相關推薦

C++ 面試題彙總

1. C++面向物件特點。 2. 多型、虛擬函式(實現原理)、純虛擬函式、抽象類及虛基類 3. 什麼是引用?引用使用時需要注意哪些? 4. 將引用作為函式引數有哪些特點? 5. 什麼時候使用常引用?將引用作為函式返回值型別的格式、好處及需要遵循的規則? 6. 引用和指標的區別? 7. 過載、

C++ 面試題彙總

1. Epoll、poll及select的區別 相同點:三者均能夠提供多路I/O複用的解決方案,在linux平臺上都可以支援。 不同點: <1> Select的本質是設定或者檢查存放檔案控制代碼(fd)的標誌位的資料結構來進行下一步處理。其缺陷是單個程序所開啟的fd是有限制的,預

面試2C/C++試題彙總微軟

1.求下面函式的返回值(微軟) int func(x) {         int countx = 0;         while(x)         {               countx ++;               x = x&(x-1);  

c++重點語法彙總2

建構函式 在定義類的物件時,系統會自動呼叫建構函式來建立並初始化物件 建構函式的申明和定義 在類體內需要宣告建構函式,形式如下:類名 ([形式引數列表]); 在類體外定義建構函式的形式如下:類名::類名([形式引數表]){函式體}//其實現

Python常見面試題彙總根據面試總結

Redis: Redis快取擊穿、快取雪崩、快取重建 回答參考: 快取擊穿:     當一個連線訪問快取資料庫中不存在的資料時,會直接通過快取資料庫到後端資料庫中查詢資料,但如果有大量連線在查詢一個不存在的資料,就會有大量連線直接訪問到後

java面試試題彙總陸續補充

最近自己也在準備面試的一方面東西,遇到一些不太熟悉的地方我會陸續補充上來。 1.選擇排序和氣泡排序 /** * 選擇排序 * @param arr * @return */ public static int[] ChooseSor

c++重點語法彙總1

繼承性 從繼承源上看,繼承可分為單一繼承和多重繼承兩種 C++語言和C語言的關係 作為面向過程的程式設計語言(C語言),C++語言與C語言的關係可以用繼承和改進來概括 C語言是C++語言的一個子集 C語言的指標在C++語言中一樣使用,但是C++語言在動態記

C# Dictionary用法彙總定義、遍歷、排序

1、Dictionary定義 Dictionary<string, double> dic = new Dictionary<string, double>(); dic.Add("語文", 98.5);          dic["數學"] = 9

C++編譯錯誤彙總持續更新

1.error C2061: 語法錯誤: 識別符號“_TCHAR”         解決方法:新增一條 #include <tchar.h> 即可成功編譯 2.VS2010中無法開啟原始檔

c++面試題整理含答案

知乎連結: 校招主要考察基礎和思維,主要涉及C++語言基礎,資料結構與演算法,TCP/IP協議,網路程式設計,Linux。 C和C++語言基礎 參考書籍:《C++ primer》,《effective C++》,《STL原始碼解析》,《深度搜索C++物件模型》

前端乾貨:前端面試題彙總推薦收藏

  HTML Doctype作用?嚴格模式與混雜模式如何區分?它們有何意義? HTML5 為什麼只需要寫 <!DOCTYPE HTML>? 行內元素有哪些?塊級元素有哪些? 空(void)元素有那些? 頁面匯入樣式時,使用link和@i

java常見面試題彙總

本期的java面試題是偏向資料庫方面的,對相關技術知識匱乏的,或者對這方面不大自信的同學,面試之前可以參考一下這套題,這只是節選,試運營一下,如果不能滿足你們的需求,可以直接評論留言!  1、檢視的優缺點 答:優點: 1)對資料庫的訪問,因為檢視可以有選擇性的選取資料庫裡的一部分。 2 )使用者

Java常見面試題彙總:spring框架

今天分享的java實習生常見面試題,是spring專場,主要是針對spring總結的面試題,有需要的小夥伴可以收入囊中了!   1、 Spring Framework 中有多少個模組,它們分別是什麼? Spring 核心容器 – 該層基本上是 Spring Framework 的核心。它包含以

Java常見面試題彙總

今天總結的是java框架相關的面試題,有需要的可以繼續拿去了。  1、J2EE 是什麼? 答:J2EE 是Sun 公司提出的多層(multi-diered),分散式(distributed),基於元件(component-base)的企業級應用模型(enterpriese application

JavaScrip常見面試題彙總含答案

一、請解釋 JavaScript 中 this 是如何工作的。 首先:this 永遠指向函式執行時所在的物件,而不是函式被建立時所在的物件。匿名函式或不處於任何物件中的函式指向 window 。 1、 方法呼叫模式 當函式被儲存為物件的一個屬性時,成該函式為該物件的方法。函式中this的

大資料常見面試題彙總

生活的本質就是快樂地分享 引導技術往熟悉的地方引導 回答問題需要做到:      簡潔、痛點 大資料的本質:從資料中挖掘價值 雲端計算的本質:共享服務【某公司筆試面試題】 1\使用mr,spark ,spark sql編寫word count程式 【Spark 版本】 va

計算機網路面試題彙總1

2.計算機網路 2.1基礎概念 1.OSI,TCP/IP,五層協議的體系結構 OSI分層(7層):物理層、資料鏈路層、網路層、傳輸層、會話層、表示層、應用層。 TCP/IP分層(4層):網路介面層、網際層、運輸層、應用層 層 協議

去BAT面試完的Mysql面試題總結55道

55道網際網路大公司的經典面試題,全部答對月薪5W+沒問題。1、一張表裡面有ID自增主鍵,當insert了17條記錄之後,刪除了第15,16,17條記錄,再把mysql重啟,再insert一條記錄,這條記錄的ID是18還是15 ?2、mysql的技術特點是什麼?3、Heap表

TCP 傳輸層面試中常問的問題彙總你所不知道的傳輸層

1. 傳輸層的主要功能是什麼? 2. 傳輸層如何區分不同應用程式的資料流?3. 傳輸層有哪些協議?4. 什麼是UDP協議?5. 為什麼有了UDP,還需要TCP?6. 什麼是TCP協議?7. 怎麼理解協議和程式?8. TCP是否真的有連結?9. 連結是如何建立的(邏輯上)?1

去BAT面試完的Mysql面試題總結55道,帶完整答案

1、一張表裡面有ID自增主鍵,當insert了17條記錄之後,刪除了第15,16,17條記錄,再把mysql重啟,再insert一條記錄,這條記錄的ID是18還是15 ? 2、mysql的技術特點是什麼? 3、Heap表是什麼? 4、mysql伺服器預設埠