先把 PPT 放出來,文章以后有空再寫吧。























解釋:integers 固定長度有什么好處?或者說為什么 <stdint.h> typedefs 沒有解決問題?
1. 格式化輸入輸出 scanf/printf,int64_t 應該用什么格式?"%d" 還是 "%ld" 還是 "%lld" ? int_fast32_t 呢?
C99 為了解決這個,引入了 inttypes.h 頭文件,其中定義了一堆宏,類似 PRId32, PRId64, PRIdFAST32,代碼寫起來是這樣:
int64_t value = getValue();
printf("value = " PRId64 "\n", value);
2. 在 C++ 里,可以用函數重載 (overload) 來解決。但是 typedef 并不真正引入新類型(golang 與此不同),你如何知道 int_fast32_t 與 int64_t 是不是同一類型呢?另外還有 size_t/time_t 呢。比如
void foo(uint64_t x)
{}
void foo(size_t x)
{}
在有的系統(64 位 Linux)下會報編譯錯,因為 size_t 和 uint64_t 都是 unsigned long 類型,不能重載 foo 兩次。怎么辦?用宏和條件編譯嗎?
另外的例子是 time_t 和 int64_t:
void bar(time_t y)
{}
void bar(int64_t y)
{}
這段代碼有錯沒錯?取決于 time_t 與 int64_t 是不是同樣的 typedef,如果整數不定長,除了用丑陋的 #if / #endif 條件編譯,有辦法解決嗎?

解釋1:finally 有什么用?確實可以用棧上對象析構函數里的動作來模擬 finally,這又是一個 idiom,為什么不正大光明地讓語言支持這一常用功能呢?
解釋2:數據成員的默認值有什么用?
如果 class Foo 有一個 enum State state_; 成員,希望初始化為 INVALID_STATE。而 Foo 有 4 個構造函數,那么你得在每個構造函數里寫:
Foo::Foo()
: state_(INVALID_STATE)
{}
Foo::Foo(XXXX1)
: state_(INVALID_STATE)
{}
Foo::Foo(XXXX1, YYYY2)
: state_(INVALID_STATE)
{}
Foo::Foo(XXXX1, YYYY2, ZZZZ3)
: state_(INVALID_STATE)
{}
state_ 的初始化要寫四處。對于 enum,或許還可以用一個公用的 init() 來初始化。那么對于 class-type 如 string/vector,用 init() 這種辦法就不能享受 initialization list 的好處了,因為對象在構造之后再被賦值,重復勞動。
更糟糕的是,萬一你將來加了一個 int turnedOn_ 成員,初始值為 -1,你得在 4 個構造函數那里去增加初始化代碼,萬一漏了一處,等待你的就是 uninitialized value,自求多福吧。
關于 allocator,它沒有帶來任何好處,如果內存分配這種事情都需要重新定義,重寫數據結構也是理所應當的:
http://blog.csdn.net/Solstice/archive/2009/08/02/4401382.aspx
auto_ptr 為什么是壞的,因為太容易用錯,且不能放到標準容器里。
Gregory Colvin 最早設計的 auto_ptr 是沒有“所有權轉移”這個語意的,跟現在的 scoped_ptr 一樣。但是標準委員會莫名其妙地加了這個語意,造成了很多陷阱。
scoped_ptr/unique_ptr/shared_ptr 都是更好的替代,語意明確,不容易用錯。
至于為什么 valarray 是壞的,見《C++ 標準程序庫》相關章節,再說,有誰會用 valarray 做科學計算嗎?同樣壞的還有 vector<bool>。
如果 XML/logging 這些基本構件不標準化,很難讓幾個第三方庫協作起來,因為每個庫都會自己發明一套互不兼容的 logging 和 XML 處理機制。
如果程序里要把 library A 生成的 XML 對象傳到 library B 里,恐怕只好用字符串來作為中間媒介,這會增加很多無謂序列化/反序列化的開銷。
logging 也是如此,如果沒有標準化接口,如何讓 library A 和 library B 按相同的格式寫到同一個日志文件呢?恐怕又得自己寫寫 adapter 來協調這些第三方庫了。
