關於面試,那些我徹底不知道的知識

這裏記錄一下在找工做前的複習過程當中那些讓我懷疑我是否是真的學過計算機的知識點。。html


C/C++

cout的格式化輸出

cout << boolalpha << (1 == 2);

輸出false
參考連接:http://www.cnblogs.com/devymex/archive/2010/09/06/1818754.html數組

const與指針

const*的左側,如 const int *aint const *a,不能改變指針a指向的內容的值
const*的右側,如 int* const a,指針a自己爲常量,不能改變a的指向ide

我的以爲把const放在類型符號後邊意義更明確一些。。函數

mutable與const

在類中,修飾爲mutable的成員變量能夠被修飾爲const的成員函數修改優化

class A {
 public:
  mutable int a;
  void set_a(int n) const {
    a = n;
  }
};

sizeof括號內的祕密

sizeof()結果由編譯時肯定,()內代碼不被執行ui

int a = 0;
sizeof(a = 1);

a的值不會被改變this

指針和引用的區別與聯繫

注意,引用也是要佔用內存空間的,內容是被引用的變量的地址,同指針同樣spa

struct st1
{
	int a;
	int &b;
	st1(int n) : a(n), b(a) {}
};

struct st2
{
	int a;
	int *b;
	st2(int n) : a(n), b(&a) {}
};

st1 s1(10);
st2 *ps2 = reinterpret_cast<st2*>(&s1);
cout << *(ps2->b); // 10

參考連接:http://blog.csdn.net/thisispan/article/details/7456169.net

指針數組,仍是數組指針,仍是函數指針數組,仍是。。

int *a[10];//包含十個元素的數組,數組元素是整型指針
int *(a[10]);//同上
int (*a)[10];//指向具備十個整型元素的數組的指針
int (*a)();//指向無參數且返回整型的函數的指針
int (*a[10])();//包含十個元素的數組,數組元素是指向無參數且返回整型的函數的指針
int (**a)[10];//指向一維數組指針的指針,數組具備十個整型元素
int *(*a)[10];//指向一維數組的指針,數組具備十個整型指針元素
int (*(*a)(int))();//指向具備一個整型參數且返回函數指針的函數的指針,返回的函數指針指向無參數且返回整型的函數

數組名取址?

int a[5] = {1, 2, 3, 4, 5};
int *p = (int*)(&a + 1);
cout << (int)*(p - 1);

輸出爲5
數組名a是指向數組第一個元素的指針,&a是指向數組的指針,雖然兩個指向同一個地址,可是&a + 1其實是將指針向後移動了sizeof(a),也就是20個字節,與a + 1移動一個字節不一樣
在這裏p相似於二維數組線程

this指針從哪來

this指針其實是類成員函數的第一個參數,由編譯器自動添加,經過寄存器傳遞,整個生命週期同函數參數一致

容器與迭代器

刪除vector等連續空間的容器元素後,相應迭代器會失效

struct與class

structclass除了默認訪問控制不一樣之外,其餘徹底相同。
struct默認訪問控制是publicclass默認訪問控制是private

構造函數初始化列表

除開父類構造函數,成員變量初始化按照成員變量在類中申明的順序執行,與初始化列表順序無關

類與內聯函數

除了虛函數和靜態成員函數,其餘函數能夠是內聯的,包括構造函數和析構函數。
事實上,若是成員函數在類申明中定義,那麼默認是內聯的。類申明外定義的函數能夠用inline修飾爲內聯的。但須要注意的是,內聯函數是內部連接的,只能在本文件內被調用。

//A.h
class A {
 public:
  A() { cout << "A()" << endl; }
  inline virtual ~A() { cout << "~A()" << endl; }
  inline void func1() { cout << "func1" << endl; }
  void func2();
};

//A.cc
inline void A::func2() { cout << "func2" << endl; }

//main.cc
A *a = new A;
a->func1();
a->func2();// 編譯失敗
delete a;

看起來好像複製構造函數

class A {
 public:
  int m;
  A(int n) : m(n) {}
  A(float n) : m(n * 2) {}
};

A a = 10;  // a.m == 10
A a = 10.0;// a.m == 20

單個參數的函數若是不添加explicit,會發生隱式的類型轉換

私有繼承與保護繼承

私有繼承與保護繼承的派生類不能稱爲子類,由於派生類並不能完成父類能作的全部事情

虛繼承與多重繼承

參考連接:http://www.oschina.net/translate/cpp-virtual-inheritance

類申明的幾個技巧

如何讓一個類不能被實例化?

將構造函數申明爲private或純虛類(抽象類)

如何讓一個類只能在堆上實例化?

將析構函數申明爲private

如何讓一個類只能在棧上實例化?

重載new運算符爲private

如何讓一個類的對象不能被複制?

將複製構造函數和賦值函數聲明爲private,或者聲明爲 = delete

如何讓一個類不能被繼承?

加final關鍵字
其餘方法:http://blog.chinaunix.net/uid-26983585-id-4373697.html

四種cast

static_cast

static_cast和C語言裏的強制類型轉換類似,不過編譯時會作類型檢查,只有相關的類型才能轉換,不然編譯錯誤

dynamic_cast

dynamic_cast在程序運行時根據對象的虛表進行向上或者向下轉換。轉換指針失敗時,返回nullptr,轉換引用失敗時,拋出異常
然而Google並不建議使用dynamic_cast,參考:http://www.zhihu.com/question/22445339

const_cast

const_cast去除對象的只讀屬性

reinterpret_cast

reinterpret_cast不作二進制轉換,僅僅是從新解釋二進制塊,經常用在偏底層的操做上,可移植性稍弱

成員函數與對象

class A {
 public:
  static int m;
  int n;
  void func1() { cout << this << ' ' << m << endl; }
  void func2() { cout << this << ' ' << n << endl; }
  static void func3() { cout << m << endl; }
};
int A::m = 10;

A *a = 0;
a->func1();// 0 10
a->func2();// crash
a->func3();// 10
A::func3();// 10

若是對象指針指向錯誤的地址,對象成員函數仍然能夠被調用,可是不能訪問非靜態成員變量。這裏同時也將靜態成員函數拿出來比較。
想想,假如成員函數是虛函數,結果還會同樣麼?

位域

struct A {
  int a:1;
  int b:2;
  int c:3;
};

cout << sizeof(A);// 4

參考連接:http://www.cnblogs.com/bigrabbit/archive/2012/09/20/2695543.html

static的三個域

  • 模塊

  • 函數

起到的做用有什麼異同

volatile

volatile關鍵字告訴編譯器不要優化被它修飾的變量,這個變量可能在編譯器控制範圍外發生改變,好比中斷或者其餘線程
注意下面這個例子

int func(volatile int *p) {
  // return (*p) * (*p); // wrong
  int temp = *p;
  return temp * temp;
}

變量提高

不一樣類型的變量參與混合運算時,全部變量將會轉換爲同一類型,爲了避免丟失精度,老是轉換爲長度更長的變量
在32位機器上,char,short老是轉換爲int,float老是轉換爲double
通常狀況下,不用關注轉換的問題,可是考慮下面一個例子:

signed char a = 0xe0;
unsigned int b = a;
cout << int(a) << ' ' << b;

結果 -32 4294967264
由於在a賦值給b時,a要提高爲32位的unsigned int型。然而a是負數,在提高長度時高位將用1來補全,因而a被提高爲0xffffffe0。賦值後,b的值爲0xffffffe0,因此做爲無符號整型輸出爲4294967264

const成員變量初始化

const成員變量必須在構造函數初始化列表中被初始化。

class A {
 public:
  const int m;
  A(int n) : m(n) {}
};

static const成員變量能夠在聲明時初始化

class A {
 public:
  static const int m = 0;
  A(int n) {}
};

static成員變量不能在聲明時初始化,也不能在構造函數初始化列表中初始化,只能在類外申明並初始化

C++ 11已經支持非靜態(static const例外)成員變量聲明時初始化,自定義類型不能執行帶參數的構造函數

函數調用方式

C和C++程序中,函數的調用有多種方式,能夠經過在函數聲明時加上__stdcall__cdecl__fastcall來顯式指定
不一樣的函數調用方式體如今參數傳遞方式,編譯後函數命名方式,函數返回時棧清理方式的不一樣。
參考連接:http://www.cnblogs.com/zhangchaoyang/articles/2725189.html

變長參數

簡單的說,具備變長參數的函數在調用時(__cdecl方式),編譯器按正常的方式將參數從右到左入棧,函數內部再經過指針根據參數類型依次從棧中將參數取出

printf("%c,%d", 'A', 10);舉慄
由於參數從右到左進棧且棧是從高地址到低地址生長的,因此此時內存是這樣的:

低地址<<|    4 byte   | 1 byte | 4 byte |>>高地址
        |"%c,%d"的地址|  'A'   |   10   |

首先printf函數的第一個參數不是變長參數,這裏咱們假設這個參數叫str,它是指向"%c,%d"的指針。有了str,咱們天然就知道了變長參數的起始地址是&str+1,而後再根據"%c,%d",咱們知道了變長參數有兩個並且類型分別爲charint,因而咱們就能夠依次獲得這兩個變量辣
參考連接:http://www.cnblogs.com/chinazhangjie/archive/2012/08/18/2645475.html

改變const變量的值

經過const_cast能夠去除read-only屬性,可是編譯時編譯器仍將使用到const變量的地方直接替換爲初始化的那個值,相似於宏

int const a = 1;
int *p = const_cast<int*>(&a);
*p = 2;
cout << a << " " << *p; // 輸出: 1 2

如何重寫基類虛函數

override,貌似又是C++ 11的關鍵字

class A {
 public:
  virtual void func(int n);
}

class B : A {
 public:
  virtual void func(int n); // 不要這樣,若是參數寫錯了,至關於聲明瞭重載函數
  void func(int n); // 同上
  void func(int n) override; // 強制重寫基類函數,若是參數或返回值與基類虛函數不一致,編譯器報錯
}

未完......

相關文章
相關標籤/搜索