目录

C++

常見問題

C++0x 概觀

基礎

  1. Ch1-2: Programming and "Hello, World!"
  2. Ch3: Objects, Types, and Values
    • 在內存中擺放資料的空間稱為物件 (object),物件有其型別 (type),內存有值 (value)。有名字 (name) 的物件稱之為變數 (variable),可透過其名提取該變數的值。

陣列

指針

int array[5] = {1, 2, 3, 4, 5};
int *ptr;
 
ptr = array;
 
*(ptr + 1) = 7;
*(array + 1) = 7; // 不可做指針運算。
   char *names[MAX] = {
                   "Zara Ali",
                   "Hina Ali",
                   "Nuha Ali",
                   "Sara Ali",
   };
int *foo() {
  static int i;
 
  int i; // 不可。此為堆疊上的位址,隨時間變化。
 
  return &i;
}

參考

類別

class Base {
public:
  virtual void foo(double i) { cout << "Base::foo(double) " << endl; }
};
 
class Derive : public Base {
public:
  // Base::foo 被 Derive:foo 給隱藏。
  // using Base::foo;
  void foo(complex<double>) { cout << "Derive::foo(complex<double>) " << endl; }
};
 
int main() {
  Derive d;
  d.foo(1l); // Derive::foo(complex<double>)
 
  Base* pd = new Derive;
  pd->foo(1); // Overload 根據靜態型別進行決議。Base::foo(double)
}

多型

基類別內要定義虛擬函式。用指針或是參考引用虛擬函式。只能用基類指針指向衍生類物件,反之不可。

class Base {
public:
  virtual ~Base() {}
  virtual void foo(int i = 10) { cout << "Base::foo(int)" << i << endl; }
};
 
class Derive : public Base {
public:
  void foo(int i = 20) { cout << "Derive::foo(int)" << i << endl; }
};
 
int main() {
  Base* pd = new Derive;
  pd->foo(); // Derive::foo(int) 10
 
  delete pd; // Base 必須要有 virtual dtor。
}

容器與迭代

Data Structure

  std::list<int> ilist = {1, 2, 3};
 
   for (auto iter = ilist.begin(); 
         iter != ilist.end(); ++iter)
     std::cout << *iter << " ";

自訂 IO

struct Entr {
  string name;
  int number ;
};
 
ostream& operator<<(ostream& os, const Entry& e)
{
  return os << "{\"" << e.name << "\", " << e.number << "\"}";
}

例外處理

int main() {
  try {
    std::cout << vec.at(3);
  }
  catch (std::out_of_range& err) {
    std::cout << "out of range!\n";
  }
}

實用組件

模板

template <typename T>
inline T const& Max (T const& a, T const& b) 
{ 
  return a < b ? b:a; 
}
template <class T>
class Stack { 
  private: 
    vector<T> elems;     // elements 
 
  public: 
    void push(T const&);  // push element 
    void pop();               // pop element 
    T top() const;            // return top element 
    bool empty() const{       // return true if empty.
        return elems.empty(); 
    } 
}; 
 
template <class T>
void Stack<T>::push (T const& elem) 
{ 
    // append copy of passed element 
    elems.push_back(elem);    
}

模板元編程

相較於傳統編程,元編程 (metaprgramming) 是在編譯時期,由編譯器進行計算。

#include <iostream>
 
// 主模板 (primary template)
template < unsigned n >
struct factorial {
  // 遞歸實例化模板 factorial<n-1>,並取得 value 成員當作其值。
  // factorial<n-1>::value 可以看做呼叫函數 factorial(n-1) 並取得返回值 value。
  static const unsigned value = n * factorial<n-1>::value;
};
 
// 顯式特化模板 (explicit specialization),用來定義終止條件。
template <>
struct factorial<0> {
  static const unsigned value = 1;
};
 
int main() {
  // 編譯器在遞歸實例化模板 factorial 的過程中會求得 n! 的值。
  std::cout << factorial<6>::value << std::endl; //  6! = 720
}

可被編譯器操縱的值稱為元數據 (meta data),常見的元數據為類型 (type) 和整數常量。為了達到靜態多型,通常會將輸入參數和返回值包裝成類型。如此一來,元函數 f 也可被包裝成類 (元函數類),再當作參數傳遞給元函數 g。元函數 g 被稱為高階元函數 (high-order function),意指元函數 g 可以操縱另一元函數 f。元函數可用來計算數值或是類型,數值會被包裝成類型,至於類型計算通常是用來判別某一類型是否具有某種特性,比如該類型是否為一整數 (int) 或是浮點數 (float)。

元函數是一個內含可被公開訪問的 type 成員的類或是樣板類。

template <class T1, class T2>
struct apply {
  typedef int type;
}

元函數類是一個內含可被公開訪問的 apply 元函數的類。

struct plus_f {
  template <class T1, class T2>
  struct apply {
    typedef int type;
  }
}

成員名 type 或是 apply 均是約定名稱。如此一來,使用者使用不同的元函數(元函數類)可以直接取用 type (apply)。 元函數轉發 (meta function forwarding) 使得子類可透過公開繼承父類,進而將父類的 type 成員暴露出來。

struct foo
  : apply
{}

數值會被包裝成類型,稱之為整型外覆器 (interal wrapper)。

// int a = int_wrapper<1>::value;
template <int x> struct int_wrapper {
  static int const value = x;
};

元數據不可變 (immutable) 且元函數沒有副作用。利用模板進行元編程,需要知道何謂模板顯式特化和部分特化。

進階

反彙編

透過反彙編可以更清楚背後運作的機制。

文章

術語

優化術語

參考書籍