技術類C++面試

導讀:
  1.已知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++) != ‘’)
  return tempptr ;
  }
  2.已知類String 的原型爲:
  class String
  {
  public:
  String(const char *str = NULL); // 普通構造函數
  String(const String &other); // 拷貝構造函數
  ~ String(void); // 析構函數
  String & operate =(const String &other); // 賦值函數
  private:
  char *m_data; // 用於保存字符串
  };
  請編寫String 的上述4 個函數。
  答案:
  String::String(const char *str)
  {
  if ( str == NULL ) //strlen在參數爲NULL時會拋異常纔會有這步判斷
  {
  m_data = new char[1] ;
  m_data[0] = ' ;
  }
  else
  {
  m_data = new char[strlen(str) + 1];
  strcpy(m_data,str);
  }
  }
  String::String(const String &other)
  {
  m_data = new char[strlen(other.m_data) + 1];
  strcpy(m_data,other.m_data);
  }
  String & String::operator =(const String &other)
  {
  if ( this == &other)
  return *this ;
  delete []m_data;
  m_data = new char[strlen(other.m_data) + 1];
  strcpy(m_data,other.m_data);
  return *this ;
  }
  String::~ String(void)
  {
  delete []m_data ;
  }
  3.簡答
  3.1 頭文件中的ifndef/define/endif 幹什麼用?
  答:防止該頭文件被重複引用。
  3.2#include 和#include “filename.h” 有什麼區別?
  答:對於#include ,編譯器從標準庫路徑開始搜索filename.h
  對於#include “filename.h”,編譯器從用戶的工作路徑開始搜索filename.h
  3.3 在C++ 程序中調用被C 編譯器編譯後的函數,爲什麼要加extern “C”?
  答:C++語言支持函數重載,C 語言不支持函數重載。函數被C++編譯後在庫中的名字與C 語言的不同。假設某個函數的原型爲: void foo(int x, int y);
  該函數被C 編譯器編譯後在庫中的名字爲_foo , 而C++ 編譯器則會產生像_foo_int_int 之類的名字。
  C++提供了C 連接交換指定符號extern“C”來解決名字匹配問題。
  3.4 一個類有基類、內部有一個其他類的成員對象,構造函數的執行順序是怎樣的。(Autodesk)
  答:先執行基類的(如果基類當中有虛基類,要先執行虛基類的,其他基類則按照聲明派生類時的順序依次執行),再執行成員對象的,最後執行自己的。
  3.5 請描述一個你熟悉的設計模式(Autodesk)
  3.6 在UML 中,聚合(aggregation)和組合(composition)有什麼區別 Autodesk)
  答案:聚合關係更強,類似於pages 和book 的關係;組合關係要弱,類似於books和bookshelf 的關係。
  3.7C#和C++除了語法上的差別以外,有什麼不同的地方?(Autodesk,Microsoft)
  答案:(C#我只是瞭解,不是很精通)
  (1) c#有垃圾自動回收機制,程序員不用擔心對象的回收。(2)c#嚴禁使用指針,只能處理對象。如果希望使用指針,則僅可在unsafe 程序塊中能使用指針。(3)c#只能單繼承。(4)必須通過類名訪問靜態成員。不能像C++中那樣,通過對象訪問靜態成員。(5)在子類中覆蓋父類的虛函數時必須用關鍵字override,覆蓋父類的方法要用關鍵字new
  3.8ADO.net 和ADO 的區別?
  答案:實際上除了“能夠讓應用程序處理存儲於DBMS 中的數據“這一基本相似點外,兩者沒有太多共同之處。但是ADO 使用OLE DB 接口並基於微軟的COM 技術,而ADO.NET 擁有自己的ADO.NET 接口並且基於微軟的.NET 體系架構。衆所周知.NET 體系不同於COM 體系,ADO.NET 接口也就完全不同於ADO和OLE DB 接口,這也就是說ADO.NET 和ADO是兩種數據訪問方式。ADO.net 提供對XML 的支持。
  3.9 New delete 與malloc free 的區別 ( Autodesk)
  答案:用malloc 函數不能初始化對象,new 會調用對象的構造函數。Delete 會調用對象的destructor,而free 不會調用對象的destructor.
  3.10 #define DOUBLE(x) x+x (Autodesk)
  i = 5*DOUBLE(10); i 是多少?正確的聲明是什麼?
  答案:i 爲60。正確的聲明是#define DOUBLE(x) (x+x)
  3.11 有哪幾種情況只能用intialization list 而不能用assignment? (Autodesk)
  答案:當類中含有const、reference 成員變量;基類的構造函數都需要參數;類中含有其他類的成員對象,而該類的構造函數都需要參數。
  3.11 C++是不是類型安全的? (Autodesk)
  答案:不是。兩個不同類型的指針之間可以強制轉換。C#是類型安全的。
  3.12 main 函數執行以前,還會執行什麼代碼? (Autodesk)
  答案:全局對象的構造函數會在main 函數之前執行。
  3.13 描述內存分配方式以及它們的區別。 (Autodesk , Microsoft)
  答案:1) 從靜態存儲區域分配。內存在程序編譯的時候就已經分配好,這塊內存在程序的整個運行期間都存在。例如全局變量,static 變量。
  (2) 在棧上創建。在執行函數時,函數內局部變量的存儲單元都可以在棧上創建,函數執行結束時這些存儲單元自動被釋放。棧內存分配運算內置於處理器的指令集。
  (3) 從堆上分配,亦稱動態內存分配。程序在運行的時候用malloc 或new 申請任意多少的內存,程序員自己負責在何時用free 或delete 釋放內存。動態內存的生存期由我們決定,使用非常靈活,但問題也最多。
  3.14 什麼是虛擬存儲器?virtual memory 怎樣映射到physical memory?頁面替換算法有哪些? (Microsoft)
  見操作系統 p238 頁。掌握的頁面替換算法NRU,FIFO,第二次機會頁面替換算法,LRU
  3.15 有四個同樣的容器,裏面裝滿了粒數相同的藥丸,正常藥丸的質量爲m,變質藥丸的質量爲m+1,現在已知這四個容器中,有一個裝的全是變質藥丸,用電子秤只稱一次,找出哪個容器裝的是變質藥丸 (Microsoft)
  答案:把四個容器依次編號爲1、2、3、4,然後從中分別取出1、2、3、4 粒藥丸,稱這10 粒藥丸的質量,如果質量爲10m+1,則說明第一個容器裝的是變質藥丸,如果爲10m+2 則說明第二個裝的變質藥丸,依次類推。
  3.16 比較一下C++中static_cast 和 dynamic_cast 的區別。 (Autodesk)
  dynamic_casts在幫助你瀏覽繼承層次上是有限制的。它不能被用於缺乏虛函數的類型上,它被用於安全地沿着類的繼承關係向下進行類型轉換。如你想在沒有繼承關係的類型中進行轉換,你可能想到static_cast
  3.17 Struct 和class 的區別 (Autodesk)
  答案:struct 中成員變量和成員函數默認訪問權限是public,class 是private
  3.18 當一個類A 中沒有生命任何成員變量與成員函數,這時sizeof(A)的值是多少,如果不是零,請解釋一下編譯器爲什麼沒有讓它爲零。(Autodesk)
  答案:肯定不是零。我舉個反例,如果是零的話,聲明一個class A[10]對象數組,而每一個對象佔用的空間是零,這時就沒辦法區分A[0],A[1]…了
  3.19 在8086 彙編下,邏輯地址和物理地址是怎樣轉換的?(Intel)
  答案:通用寄存器給出的地址,是段內偏移地址,相應段寄存器地址*10H+通用寄存器內地址,就得到了真正要訪問的地址。
  3.20 描述一下C++的多態 (microsoft)
  答案:C++的多態表現在兩個部分,一個是靜態連編下的函數重載,運算符重載;動態連編下的虛函數、純虛函數(抽象類)
  4.寫出BOOL,int,float,指針類型的變量a 與零的比較語句。
  答案:
  BOOL : if ( !a )
  int : if ( a == 0)
  float : const EXPRESSION EXP = 0.000001
  if ( a < EXP && a >-EXP)
  pointer : if ( a != NULL)
  5.請說出const 與#define 相比優點
  答案:
  (1) const 常量有數據類型,而宏常量沒有數據類型。編譯器可以對前者進行類型安全檢查。而對後者只進行字符替換,沒有類型安全檢查,並且在字符替換可能會產生意料不到的錯誤。
  (2) 有些集成化的調試工具可以對const 常量進行調試,但是不能對宏常量進行調試。
  6.簡述數組與指針的區別
  數組要麼在靜態存儲區被創建(如全局數組),要麼在棧上被創建。指針可以隨時指向任意類型的內存塊。
  (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 字節
  }
  7.類成員函數的重載、覆蓋和隱藏區別
  答案:
  成員函數被重載的特徵:
  (1)相同的範圍(在同一個類中);
  (2)函數名字相同;
  (3)參數不同;
  (4)virtual 關鍵字可有可無。
  覆蓋是指派生類函數覆蓋基類函數,特徵是:
  (1)不同的範圍(分別位於派生類與基類);
  (2)函數名字相同;
  (3)參數相同;
  (4)基類函數必須有virtual 關鍵字。
  “隱藏”是指派生類的函數屏蔽了與其同名的基類函數,規則如下:
  (1)如果派生類的函數與基類的函數同名,但是參數不同。此時,不論有無virtual關鍵字,基類的函數將被隱藏(注意別與重載混淆)。
  (2)如果派生類的函數與基類的函數同名,並且參數也相同,但是基類函數沒有virtual 關鍵字。此時,基類的函數被隱藏(注意別與覆蓋混淆)
  8.There are two int variables: a and b, don’t use “if”, “? :”, “switch”
  or other judgement statements, find out the biggest one of the two
  numbers.
  答案:( ( a + b ) + abs( a – b ) ) / 2
  9.如何打印出當前源文件的文件名以及源文件的當前行號?
  答案:
  cout << __FILE__ ;
  cout<<__LINE__ ;
  __FILE__和__LINE__是系統預定義宏,這種宏並不是在某個文件中定義的,而是由編譯器定義的。
  10.main 主函數執行完畢後,是否可能會再執行一段代碼,給出說明?
  答案:可以,可以用_onexit 註冊一個函數,它會在main 之後執行int fn1(void), fn2(void), fn3(void), fn4 (void);
  void main( void )
  {
  String str("zhanglin");
  _onexit( fn1 );
  _onexit( fn2 );
  _onexit( fn3 );
  _onexit( 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 _onexit function is passed the address of a function (func) to be called when the program terminates normally. Successive calls to _onexit create a register of functions that are executed in LIFO (last-in-first-out) order. The functions passed to _onexit cannot take parameters.
  11.如何判斷一段程序是由C 編譯程序還是由C++編譯程序編譯的?
  答案:
  #ifdef __cplusplus
  cout<<"c++";
  #else
  cout<<"c";
  #endif
  12.文件中有一組整數,要求排序後輸出到另一個文件中
  答案:
  void Order(vector  {
  int count = data.size() ;
  int tag = false ;
  for ( int i = 0 ; i < count ; i++)
  {
  for ( int j = 0 ; j < count - i - 1 ; j++)
  {
  if ( data[j] > data[j+1])
  {
  tag = true ;
  int temp = data[j] ;
  data[j] = data[j+1] ;
  data[j+1] = temp ;
  }
  }
  if ( !tag )
  break ;
  }
  }
  void main( void )
  {
  vectordata;
  ifstream in("c://data.txt");
  if ( !in)
  {
  cout<<"file error!";
  exit(1);
  }
  int temp;
  while (!in.eof())
  {
  in>>temp;
  data.push_back(temp);
  }
  in.close();
  Order(data);
  ofstream out("c://result.txt");
  if ( !out)
  {
  cout<<"file error!";
  exit(1);
  }
  for ( i = 0 ; i < data.size() ; i++)
  out<  }
  ~B()
  {
  cout<<"destructed"<  }
  B(int i):data(i)
  {
  cout<<"constructed by parameter" << data <  }
  private:
  int data;
  };
  B Play( B b)
  {
  return b ;
  }
  int main(int argc, char* argv[])
  {
  B temp = Play(5);
  return 0;
  }
  請自己執行一下看看。
  16.寫一個函數找出一個整數數組中,第二大的數 (microsoft)
  答案:
  const int MINNUMBER = -32767 ;
  int find_sec_max( int data[] , int count) //類似於1 4 4 4這樣的序列將認爲1是第二大數
  {
  int maxnumber = data[0] ;
  int sec_max = MINNUMBER ;
  for ( int i = 1 ; i < count ; i++)
  {
  if ( data[i] > maxnumber )
  {
  sec_max = maxnumber ;
  maxnumber = data[i] ;
  }
  else
  {
  if ( data[i] > sec_max )
  sec_max = data[i] ;
  }
  }
  return sec_max ;
  }
  17 寫一個在一個字符串中尋找一個子串第一個位置的函數
  這個題目的一般算法比較簡單我就不給出了,如果要求高效率的話請參見數據結構中的KMP 算法,不過在筆試時間有限情況下,寫出那個算法還是挺難的。
  英文題目
  1. Introduce yourself in English
  2. What is your great advantage you think of yourself?
  3. What is your drawback you think of yourself?
  4. How do you feel shanghai?
  改用c++繼續轟炸,寫構造函數和賦值運算符。
  虛函數的一些東東,還有cast。
  3.
  stl 裏面vector的實現(內部空間的申請與分配)--我暈 這個我也不會,沒看過
  struct /class的區別
  爲什麼要用struct //成員的默認屬性不同,用struct的話,主要是作爲數據的集合
  怎樣使一個class不能被實例化 //1,構造函數私有化,2,抽象類
  私有繼承和public繼承的區別。 //is-a has-a
  void *p的問題 //不能++
  引用和指針的區別與聯繫。引用是否可以更改 //引用類似於常量指針,一旦初始化,不
  能更改。
  windows編程基礎,線程與進程的區別 //我竟然忘了
  com+是否熟悉,(沒用過)
  還問了我幾個我都沒有聽說過的名詞
  然後就是數據結構/算法的問題
  簡述一下hash算法
  一個32位的數據,怎樣找到最左邊的一個1
  一個4*4的格子,填入1~15 然後給個目標狀態,怎樣去搜索。
  給你100萬個數據,數據的值在0~65535之間 用最快的速度排序
  最後一個問題:
  如果我們的一個軟件產品,用戶回覆說:運行速度很慢,你怎麼處理
  1,hash算法,這個我忘得差不多了,他給了我一個提示,我想起來了。ok
  2,n位的2進制數據怎樣找罪左邊的1,如果是在最左位,這個數是負數,否則的話,左移
  一位,看是否變成負數,這是O(n)的算法,O(n/2)的算法:二分方式查找
  3,廣度優先搜索+啓發式
  4,統計每個數字出現的頻率
  5,這個我也沒經驗,亂說了一通。
  一上來面試官就說,根據你的簡歷,我們會關注與算法方面的問題,
  1,八皇后問題,詳述解法 ---輕鬆搞定
  2,kmp快速匹配算法 ---不算輕鬆的搞定
  3,無向圖中兩點間最短路問題 ---偉大的迪傑克斯拉算法
  4,空間中任意給兩個向量,求角平分線 他給了個提示,解決
  5,什麼是平衡樹 ---光說上概念來了,其他的不會了(昨晚光看b-,b+樹了)
  6,哈夫曼編碼問題 ---回答的有些混亂
  7,求1~10000的素數 ---篩選法,有點細節沒處理好
  8,有向圖求環 ---我只會搜索,在他的提示下,還是沒有做出來
  9,給n個點,求凸包問題 ---hiahia,牛X一把,用二分作的!
  10,堆排序 ---明確地告訴了他,俺忘了
  11,四則運算
  (1)給一個前綴表達式,然後求解 ---勉強做上來了
  (2)給一箇中綴表達式,求解 ---更勉強的作上來了
  12,正則表達式
  然後,換人,考智力:
  1,3個門,分別叫做:日月星
  日:此門通向光明
  月:此門非通向光明
  星:月非通向光明
  至少一個說真話,至少一個說假話,一個通向光明
  問:誰通向光明,----答:星,需要假設來做
  2,不均勻的繩子測一個小時,答:兩頭燒,---我和他討論了一下,是否可能無法解決,
  他說,就是兩頭燒
  3,一個長方形,裏面隨即挖去另一個長方形,一刀把它平分。---中點相連接
  4,4個人過河,怎樣最快 1,2,5,7。 答:我以前做過,給我點時間
  5,給你三個盒子,其中一個放了東西,你指定一個,然後打開另外兩個中的一個,發現是
  空的,問:你是否要改變你的選擇。 答:我覺着不應該改變,但他說要改變,我想了半天
  ,沒想出來,放棄
  6, 1,2,5 3中硬幣,有無數個,然後給你個n,讓你用最少的硬幣數組成n ---我竟然用
  動態規劃作,他告訴我,麻煩了, 貪心,搞定
  7,開放性題目:怎樣測一個飛機的重量,---答:問廠商,問:還有呢?答:根據發動機
  的推力和耗油量,可以推出一個大體值,但有很多影響因素,放棄。
  8,給一個正方體,兩個對面上有兩個點,沿着體表面,找一條最短路,---答:拆開,
  直線最短
  期間還問了我 線程和進程的區別,---答:上次問過了。
  5.1.STL中container有哪些?
  答:vector,list,set,multiset,map,multimap,deque,bitset
  2.map中的數據存儲方式是什麼?
  答:Hashtable
  3.map和hashmap有什麼區別?
  答:不知道。
  4.hashmap是標準庫中的嗎?
  答:不是。
  5.vector中的erase方法跟algorithm的remove有什麼區別?
  答:我不怎麼清楚,只知道remove_if可以用function object。還有可能vector自帶的erase在執行過後會有一些優化的方法吧。
  6.function object是什麼?
  答:(這個我說了半天,反正就是描述一下)
  大概就是這麼幾道題,他問我的STL不多,歡迎大家討論:)
  其他部分過幾天陸續放出,敬請期待!
  5 1. C++中如何阻止一個類被實例化?
  答:抽象類,或者構造函數被聲明成private
  2. 一般在什麼時候構造函數被聲明成private呢?
  答:比如要阻止編譯器生成默認的copy constructor
  3. 什麼時候編譯器會生成默認的copy constructor呢?
  答:只要自己沒寫,而程序中需要,都會生成
  4. 如果你已經寫了一個構造函數,編譯器還會生成copy constructor嗎?
  答:會
  5. struct和class有什麼區別?
  答:默認的訪問級別不同,struct是public,class是private
  6. 沒有別的不同了嗎?
  答:好像沒有了吧……
  7. 爲什麼說如果一個類作爲基類,則它的析構函數要聲明成virtual的?
  答:(Effective C++ 條款14,我當時剛剛複習過,呵呵)
  8. inline的函數和#define有什麼區別?
  答:類型檢查
  9. inline是什麼意思?
  答:就是不產生call,直接把函數的代碼嵌入程序。但是inline不是強制的,是
  編譯器根據需要決定函數是否真的被inline
  10. 那你說說什麼時候會真的被inline,什麼時候不會呢?
  答:(略)
  11. 如果把一個類的成員函數寫在類的聲明中是什麼意思?
  答:inline
  12. public繼承和private繼承有什麼架構上的區別?
  答:public是is-a的關係,private是has-a的關係
  13. 在多繼承的時候,如果一個類繼承同時繼承自class A和class B,而class A和
  B中都有一個函數叫foo(),如何明確的在子類中指出override哪個父類的foo()?
  答:虛擬繼承吧……(我想了半天也不記得這個怎麼弄了,他也就沒有繼續難爲
  我)
  14. 虛擬繼承的語法是什麼?
  答:class C : public A, virtual public B
  15. 部分模版特例化(我忘了他當時怎麼翻譯這個詞的了,反正就是partial temp
  late specialization)和全部模版特例化有什麼區別?
  答:(想了半天)就是是不是還有一個通用的模版的區別。這個特性在VC中不支
  持,所以我不是很熟悉,不好意思……
  16. 哦?VC不支持?你確定
  答:確定!(.net剛出的時候,我特意看過MSDN,上面寫着VC7.0中有3個C++的
  特性沒有支持,其中就有這個,沒想到他連這個都考!)
  6大家討論啊!希望對我的回答更正一下,謝謝:)
  1.編一個函數,使一個單項鍊錶轉置。
  2.拆解一個整數,比如4,可以拆解成
  4=3+1
  4=2+2
  4=2+1+1
  4=1+1+1+1
  3.哈希表
  4.不用庫函數,實現strcpy或者memcpy等函數

本文轉自
http://hi.baidu.com/pkugsis/blog/item/21bf392a943d54385243c135.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章