最簡單的知識有時間記憶回憶起來卻最難.
1.類型轉換會產生臨時變數
(const std::vector<ACE_INT32>)類型轉換將導致產生新的臨時變數. 所以先做類型轉換,再取其地址或其內部屬性地址時危險的.
2.delete null不會coredump
這麼多年C++才知道,當然學校時是連什麼是coredump都不知道地
刪除null 指標是安全的(因為它什麼也沒做)。
在定義指標變數時初始化為要麼指向有效記憶體,要麼就指向空,那在你的該變數要失效時就可以只用簡單地 delete 掉他們,而不用擔心他們是不是被new過。
3.傳回值範圍擴充
string GetString(){}
const char *pTemp = GetString().c_str();
printf("%s", pTemp)
const string& temp = GetString();
printf("%s", temp.c_str())
上面兩段區別就是:擴充了傳回值範圍,第二種將傳回值的範圍擴充到了當前函數,第一種傳回值範圍僅僅在當前行.
4.C++三個特性
封裝/繼承/多態
5.dynamic_cast 在進行類型動態轉換時不會Core掉的,也就是可以不判空,直接轉換之後再判,當然轉換失敗倘若原來指標沒釋放會有記憶體泄露的危險.
dynamic_cast 效能比較低,需要注意使用
6.虛繼承
7.volatile
volatile 相當於告訴編譯器, 由它聲明的東西的易變的, 不確定的, 可能由外部程式 (如中斷程式) 改變的, 禁止編譯器對其讀寫或其他動作進行最佳化
如果定義: int i;
則編譯器可能會將其最佳化, 而放到 CPU 寄存器中, 這在多數情況下是好的,對i的後續訪問就可以不用再讀記憶體了;
然而在有些情況下,比如i被多線程訪問到 我們會要求一些變數必須在記憶體中 (如驅動程式, 中斷處理常式等等), 這時編譯器這個最佳化就是引起問題, 為了避免這種情況, 應該這樣定義: volatile int i;
常見用法:#define flashctrl (*(volatile unsigned *)(memory+0x00) // 指向的記憶體為多線程所共用
volatile 通常也用來阻止編譯器具最佳化操作, 如你有一個非精確延時函數: void delay(unsigned int timeout) { unsigned int i; for (i = 0; i < timeout; i++); } 有些編譯會足夠聰明地注意到這個函數本質上是什麼也沒幹, 會將針對這個函數的調用最佳化掉, 但這樣是不對的, 所以你應該這麼聲明: volatile void delay(...) { // 同上 }
8. 範圍和連結(extern)之間的關係(之前倒是考慮過,看到這樣的描述,趕緊省事兒記下)
範圍是為編譯器服務的,而連結是為連結器服務的.編譯器用標識符的範圍來確定在檔案的給定位置訪問標識符是否合法.當編譯器把源檔案翻譯成目標代碼時,它會注意到有外部連結的名字,並最終把這些名字儲存到目標檔案內的一個表中.因此,連結器可以訪問到具有外部連結的名字,而內部連結的名字或不需連線的名字對連結器而言是不可見的.
變數的預設儲存期限,範圍和連結都依賴於變數聲明的位置.
(1)在塊內部聲明的變數具有自動儲存期限,塊範圍,並且無連結
(2)在程式的最外層(任意塊外部)聲明的變數具有靜態儲存期限,檔案範圍和外部連結.
可以通過(auto,static,extern和register)來改變變數的性質
(1)static作用於塊內部聲明的變數時,變數具有靜態儲存期限(塊範圍,無串連)
static範圍塊外部變數時,變數是內部連結(靜態儲存期限,檔案範圍)
注意:雖然函數不應該返回指向auto變數的指標,但是函數返回指向static變數的指標是沒有錯誤的.
(2)extern聲明中的變數始終具有靜態儲存期限.不改變變數的範圍
確定其連結具有一定的難度.一般具有外部連結,如果變數在較早的位置聲明為static,那麼具有內部連結
extern的重要用處是對變數或函數的聲明(不進行定義)
一個名字具有塊範圍卻有外部連結(本身沒什麼特別,就這個說法比較奇怪)
比如在第一個檔案中定義:
int i;
並且i是放在了任意函數外,所以預設情況下具有外部連結。在另一個檔案中,函數f需要訪問變數i,所以可以把i聲明在f內:
void f(void)
{
extern int i;
....
}
在第一個檔案中i具有外部範圍,在第二個檔案中i具有塊範圍。
9. 哪個無限迴圈格式更可取,while(1)還是for(;;)
C程式員傳統上喜歡for(;;)的高效性,因為早期的編譯器經常強製程序在每次執行while迴圈體時測試條件1.但是對現代編譯器來說,在效能上兩種無限迴圈應該沒有差別.只是習慣問題了
10.宏定義都是全域的
前段時間同事分析一編譯不過問題,就是一個宏在命名空間A裡,竟然影響到一個不在命名空間A裡同名常量以致編譯不過。自己可能能分析出來也可能不能。
後面原因便是宏是全域的,並不受限於命名空間。
因為宏是在先行編譯時展開的,作為先行編譯當時應該是沒有命名空間的,所以宏是全域應該很好理解。
11.explicit
explicit 只對建構函式起作用,用來抑制隱式轉換。
12.mutable
mutable 也是為了突破const的限制而設定的。被mutable修飾的變數,將永遠處於可變的狀態,即使在一個const成員函數中也可以修改mutable修改的成員變數。