In call-by-value, the argument expression is evaluated, and the resulting value is bound to the corresponding variable in the function (frequently by copying the value into a new memory region).
In call-by-reference evaluation (also referred to as pass-by-reference), a function receives an implicit reference to a variable used as argument, rather than a copy of its value.
#include <iomanip> #include <sstream> #include <string> template< typename T > std::string int_to_hex( T i ) { std::stringstream stream; stream << "0x" << std::uppercase << std::setfill ('0') << std::setw(sizeof(T)*2) << std::hex << i; return stream.str(); }
for (auto it = c.begin(); it != c.end(); /* "it" updated inside loop body */ ) { if ( erasing_condition(*it) ) { // Erase the element matching the specified condition // from the associative container. it = c.erase(it); // Note: // erase() returns an iterator to the element // that follows the last element removed, // so we can continue the "for" loop iteration from that position. } else { // Current element does _not_ satisfy erasing condition, // so we can just move on to the next element. ++it; } }
int main () { // an array with 5 rows and 2 columns. int a[5][2] = { {0,0}, {1,2}, {2,4}, {3,6},{4,8}}; // output each array element's value for ( int i = 0; i < 5; i++ ) for ( int j = 0; j < 2; j++ ) { cout << "a[" << i << "][" << j << "]: "; cout << a[i][j]<< endl; } return 0; }
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; }
int i; int &r = i; // 必須要有初值,無法像指針一樣可以有空指針。 void swap(int& a, int& b); int& foo() { static int i; return i; }
class Base { void foo(int); void foo(double); }; void bar(int); void bar(double);
class Base { // 要做到動態多型,宣告成 virtual。 void foo(int); }; class Derive : public Base { void foo(int) { /* do different thing */ } };
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。 }
class Shape { public: // 其中定義有一個純虛擬函式,留待子類別實作。 virtual void draw() = 0; };
std::list<int> ilist = {1, 2, 3}; for (auto iter = ilist.begin(); iter != ilist.end(); ++iter) std::cout << *iter << " ";
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"; } }
#include <memory> int main() { std::unique_ptr<int> p1(new int(5)); std::unique_ptr<int> p2 = p1; // p1 獨占該指針所有權,無法轉移。 std::cout << *p1; /* 不需要手動 delete */ // delete p1; }
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) 且元函數沒有副作用。利用模板進行元編程,需要知道何謂模板顯式特化和部分特化。
透過反彙編可以更清楚背後運作的機制。
// Constant Addresses of Hardware Registers // p_led_reg 是一個 constant 指針,指向一個 volatile uint8_t。 uint8_t volatile * const p_led_reg = (uint8_t *) 0x00080000; // Read-Only Shared-Memory Buffer int const volatile comm_flag; uint8_t const volatile comm_buffer[BUFFER_SIZE]; // Read-Only Hardware Register uint8_t const volatile * const p_latch_reg = (uint8_t *) 0x10000000;