筆試整理之C++基礎試題

1、i++跟++i

(1)單獨執行後,i的值都增加了1


(2)i++不可以做左值,++i可以

<1>左值:C/C++語言中可以放在賦值符號左邊的變量,即具有對應的可以由用戶訪問的存儲單元,並且能夠由用戶去改變其值的量。

<2>具體函數實現:

// 前綴形式:

int& int::operator++() //這裏返回的是一個引用形式,就是說函數返回值也可以作爲一個左值使用
{//函數本身無參,意味着是在自身空間內增加1的
  *this += 1;  // 增加
  return *this;  // 取回值
}

//後綴形式:
const int int::operator++(int) //函數返回值是一個非左值型的,與前綴形式的差別所在。
{//函數帶參,說明有另外的空間開闢
  int oldValue = *this;  // 取回值
  ++(*this);  // 增加
  return oldValue;  // 返回被取回的值

}


2、C++ 的一個常見面試題是讓你實現一個 String 類,限於時間,不可能要求具備 std::string 的功能,但至少要求能正確管理資源。

此題轉載至:http://coolshell.cn/articles/10478.html

首先選擇數據成員,最簡單的 String 只有一個 char* 成員變量。

好處是容易實現,壞處是某些操作的複雜度較高(例如 size() 會是線性時間)。

爲了面試時寫代碼不出錯,本文設計的 String 只有一個 char* data_成員。

而且規定 invariant 如下:一個 valid 的 string 對象的 data_ 保證不爲 NULL,data_ 以 '\0' 結尾,以方便配合 C 語言的 str*() 系列函數。
其次決定支持哪些操作,構造、析構、拷貝構造、賦值這幾樣是肯定要有的(以前合稱 big three,現在叫 copy control)。

如果鑽得深一點,C++11的移動構造和移動賦值也可以有。

爲了突出重點,本文就不考慮 operator[] 之類的重載了。

這樣代碼基本上就定型了:

  1. #include <utility> 
  2. #include <string.h> 
  3.   
  4. class String 
  5.  public
  6.   String() 
  7.     : data_(new char[1]) 
  8.   { 
  9.     *data_ = '\0'
  10.   } 
  11.   
  12.   String(const char* str) 
  13.     : data_(new char[strlen(str) + 1]) 
  14.   { 
  15.     strcpy(data_, str); 
  16.   } 
  17.   
  18.   String(const String& rhs) 
  19.     : data_(new char[rhs.size() + 1]) 
  20.   { 
  21.     strcpy(data_, rhs.c_str()); 
  22.   } 
  23.   /* Delegate constructor in C++11 
  24.   String(const String& rhs) 
  25.     : String(rhs.data_) 
  26.   { 
  27.   } 
  28.   */ 
  29.   
  30.   ~String() 
  31.   { 
  32.     delete[] data_; 
  33.   } 
  34.   
  35.   /* Traditional: 
  36.   String& operator=(const String& rhs) 
  37.   { 
  38.     String tmp(rhs); 
  39.     swap(tmp); 
  40.     return *this; 
  41.   } 
  42.   */ 
  43.   String& operator=(String rhs) // yes, pass-by-value 
  44.   { 
  45.     swap(rhs); 
  46.     return *this
  47.   } 
  48.   
  49.   // C++ 11 
  50.   String(String&& rhs) 
  51.     : data_(rhs.data_) 
  52.   { 
  53.     rhs.data_ = nullptr; 
  54.   } 
  55.   
  56.   String& operator=(String&& rhs) 
  57.   { 
  58.     swap(rhs); 
  59.     return *this
  60.   } 
  61.   
  62.   // Accessors 
  63.   
  64.   size_t size() const 
  65.   { 
  66.     return strlen(data_); 
  67.   } 
  68.   
  69.   const char* c_str() const 
  70.   { 
  71.     return data_; 
  72.   } 
  73.   
  74.   void swap(String& rhs) 
  75.   { 
  76.     std::swap(data_, rhs.data_); 
  77.   } 
  78.   
  79.  private
  80.   char* data_; 
  81. }; 

注意代碼的幾個要點:

  1. 只在構造函數裏調用 new char[],只在析構函數裏調用 delete[]。
  2. 賦值操作符采用了《C++編程規範》推薦的現代寫法。
  3. 每個函數都只有一兩行代碼,沒有條件判斷。
  4. 析構函數不必檢查 data_ 是否爲 NULL。
  5. 構造函數 String(const char* str) 沒有檢查 str 的合法性,這是一個永無止境的爭論話題。這裏在初始化列表裏就用到了 str,因此在函數體內用 assert() 是無意義的。

這恐怕是最簡潔的 String 實現了。

練習1:增加 operator==、operator<、operator[] 等操作符重載。

練習2:實現一個帶 int size_; 成員的版本,以空間換時間。

練習3:受益於右值引用及移動語意,在 C++11 中對 String 實施直接插入排序的性能比C++98/03要高,試編程驗證之。(g++的標準庫也用到了此技術。)


3.描述在瀏覽器中敲入一個網址並按下回車後所發生的事情//比如 www.baidu.com


(1)DNS域名解析

首先要查找域名的IP地址,經過DNS查找後,將輸入網址域名轉換成IP地址。如果url裏不包含端口號,則會使用該協議的默認端口號。DNS域名解析的過程是這樣的:首先我們知道我們本地的機器上在配置網絡時都會填寫DNS,這樣本機就會把這個url發給這個配置的DNS服務器,如果能夠找到相應的url則返回其ip,否則該DNS將繼續將該解析請求發送給上級DNS,整個DNS可以看做是一個樹狀結構,該請求將一直髮送到根直到得到結果。

(2)在發送請求前,先要建立一個TCP連接(socket連接)。socket通過ip和端口建立的,現在有了目標ip和端口號。

(3)建立連接後發送請求。瀏覽器給web服務器發送一個HTTP請求。請求中也包含瀏覽器存儲的該域名的cookies。cookies是與跟蹤一個網站狀態相匹配的鍵值。cookies會存儲登錄用戶名,服務器分配的密碼和一些用戶設置等。Cookies會以文本文檔形式存儲在客戶機裏,每次請求時發送給服務器。

(3)服務的永久重定向響應
(4)瀏覽器跟蹤重定向地址
(5)服務器“處理”請求:應答 web服務器收到請求,進行處理。 從它的文檔空間中搜索子目錄index.html。如果找到該文件,Web服務器把該文件內容傳送給相應的Web瀏覽器;未找到,返回錯誤信息。爲了告知瀏覽器,Web服務器首先傳送一些HTTP頭信息,然後傳送具體內容(即HTTP體信息),HTTP頭信息和HTTP體信息之間用一個空行分開
(6)服務器發回一個HTML響應

(7)釋放 TCP 連接:若connection 模式爲close,則服務器主動關閉TCP 連接,客戶端被動關閉連接,釋放TCP 連接;若connection 模式爲keepalive,則該連接會保持一段時間,在該時間內可以繼續接收請求
(8)瀏覽器開始顯示HTML
(9)瀏覽器發送獲取嵌入在HTML中的對象


參考網址:http://www.mamicode.com/info-detail-1357508.html


4.strcpy和memcpy的區別 ()

strcpy和memcpy都是標準C庫函數,它們有下面的特點。
strcpy提供了字符串的複製。即strcpy只用於字符串複製,並且它不僅複製字符串內容之外,還會複製字符串的結束符。

已知strcpy函數的原型是:char* strcpy(char* dest, const char* src);
memcpy提供了一般內存的複製。即memcpy對於需要複製的內容沒有限制,因此用途更廣。
void *memcpy( void *dest, const void *src, size_t count );

char * strcpy(char * dest, const char * src) // 實現src到dest的複製
{
  if ((src == NULL) || (dest == NULL)) //判斷參數src和dest的有效性
  {
      return NULL;
  }
  char *strdest = dest;        //保存目標字符串的首地址

  while ((*strDest++ = *strSrc++)!='\0'); //把src字符串的內容複製到dest下

  return strdest;
}


void *memcpy(void *memTo, const void *memFrom, size_t size)
{
  if((memTo == NULL) || (memFrom == NULL)) //memTo和memFrom必須有效
         return NULL;

  char *tempFrom = (char *)memFrom;             //保存memFrom首地址
  char *tempTo = (char *)memTo;                  //保存memTo首地址      
  while((size-- )> 0)                //循環size次,複製memFrom的值到memTo中
         *tempTo++ = *tempFrom++ ;  
  return memTo;



strcpy和memcpy主要有以下3方面的區別。
1、複製的內容不同。strcpy只能複製字符串,而memcpy可以複製任意內容,例如字符數組、整型、結構體、類等。
2、複製的方法不同。strcpy不需要指定長度,它遇到被複制字符的串結束符"\0"才結束,所以容易溢出。memcpy則是根據其第3個參數決定複製的長度。
3、用途不同。通常在複製字符串時用strcpy,而需要複製其他類型數據時則一般用memcpy


發佈了18 篇原創文章 · 獲贊 29 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章