精華區beta C_and_CPP 關於我們 聯絡資訊
和大家聊聊這本書的一點心得。 p23 提到 Cpre (1981 第一個發佈版本), 這是 c with class 的 preprocessor。 p34 說明 this 為什麼是 this 而不是 self (取自 simula), 為什麼是 pointer 而不是 reference (因為這時候還沒有 reference) c 語言的 f(void), 竟然是被 Bjarne 所遺棄的語法, c++ f() 相當於 c f(void), 這是 和 c 不同的地方, 也就是和 c 不相容, 所以 c++ 真的是另外一種語言。 2.7 (p37) 這應該是很多人的疑問, 為什麼是架構在 c 而不是發明一個全新的語言? Bjarne 大約用了兩頁在說明原因, 並提到從 simula, algol68, bcpl 那裡「偷」了什麼 特性用到 c++ 中。 2.8.1 介紹了 -> 來代替 *, 這是為了改善 c 的宣告語法, 我的老天, 還好最後 Bjarne 沒這麼做。int v[10]-> 等同於 int *v[10], int f(char)->[10]->(double)-> 對於習慣 c 宣告的我來說, 這似乎也不怎麼高明. 讓 typedef 來對付複雜宣告就好。 c++ 一開始被取名為 C84 (一點都不威阿), 後來 Rick Mascitti 提出了 c++ 這個名字 (真是厲害), 這個名字看來厲害多了。 g++ 1.13 在 198712 公佈, 這是第一個 g++ 版本。 cfront (1984/08 第一個發佈版本) 1986 移植到 pc/at, cfront 並不是 c++ compiler, p59 有張圖可以了解 cfront 的角色, 簡單說透過 cfront 產生的原始碼還要 經過 c compiler, 所以才叫 cfront。 c++ 的設計理念之一, 『你只需要為你用的東西付出代價。』用上 class, 和 c 的 struct 一樣, 不會有任何負擔, 加上 virtual function, 呃 ... 這和 c 就不同了, 得 付出一點代價。 p77 介紹了對於 operator[]() 這個 operator 重新定義時會有的問題, 以 string 為例 子, 引入了輔助用 class 來分別處理左值、右值, 真是巧妙。 garbage collection 在 2.13, 3.9, 10.7 被談到, 尤其是 10.7 花了不少篇幅在討論 garbage collection 所帶來的空間/時間開銷, 這會讓 c++ 威力大減。只提出了 optional garbage collection 的概念, c++11 似乎要加入這個, 我不相信魚與熊掌能兼 得, 希望這功能是可以關閉的, 而不是強迫使用。 3.8 對於 const 這個關鍵字的意義在 c 和 c++ 有所不同, 不過 const 關鍵字可是由 Bjarne 引進到 c 的, 意外吧! 不過當時使用的是 readonly, writeonly 這兩個關鍵字 , 最後是由 ANSI C 改用 const 而成為 C 標準, 這是 Bjarne 第一次的標準化經驗 (對 象是 c 語言), 不過 c 的 const 無法使用 const expression, 和 c++ 的 const 語意 所有不同。 ex: const int max = 14; int a[max+1]; 在 c 無法這樣使用。別再說 c++ 改變了 c 的 const 用法, 而是 ANSI C 標準委員會沒 有採納 Bjarne 的 const 用法。 3.11.1 // 則是由 BCPL 的注解風格, 因為還蠻好用的, Bjarne 就引進了 c++, C99 也支援這個 注解風格。 3.11.4 在探討 initialization of global objects, Bjarne 並不是只考慮完成這功能 , 還要考慮效率問題, C++ 的設計原則: "a C++ feature not only has to be usefuel, it also has to be affordable." 這個 c++ 特性不只要有用, 還要能負擔的起 (直翻就是這樣, 完全沒有美感, 請原諒我) 。而這個解決辦法會帶來效率上的問題, 所以才說負擔不起。這個方法是 Jerry Schwarz 所提供。現在的 c++ 似乎已經解決這問題 (我不確定)。 有興趣可參考完整圖文: descent-incoming.blogspot.tw/2014/01/books-design-and-evolution-of-c.html -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 58.114.151.71
uranusjr:所以 C++ 用 this 而非 self 的原因是? 01/06 01:24
littleshan:因為 simula 用 this 啊 01/06 01:51
yoco315:好文耶 01/06 11:00
uranusjr:就只有這樣喔, 我還以為是有什麼理由... orz 01/06 12:47
ukjhsa:好文推 01/06 16:21
soheadsome:好文 可以縮一下網址 01/06 17:28
> -------------------------------------------------------------------------- < 作者: GameHeven (Mark Williams) 站內: C_and_CPP 標題: Re: [分享] The Design and Evolution of C++ 心得 時間: Wed Jan 15 20:30:50 2014 看了這篇文,我也去找這本書來看。這本是1994年出版,20年前的舊書。 世界級的大師真的很強。 一般人對C++提出的質疑,其實他早在20年前全部都想到了。 有些真的無解,所以不改。 有些是效率太差,所以不加這功能。 有些是時間不夠,等到下一版再改。 Bjarne設計的時候,一直保持幾個大原則。 盡量與純C相容。不要求100%,但是要有99%相容。 函式庫可以作到的事情,就直接用函式庫解決。加入新特性是最後手段。 盡量不要新增關鍵字,如果真的要加,盡量用冷門的單字。 不需要為你沒用到東西付出代價。 所有功能都要考量「現實」。 包括執行效率/編譯效率/編譯器能不能實做。 實做過度困難,那就不加。 效率過差,只有高級電腦能用,那就先不加。等以後硬體進步再加。 ============================================================================== 最原始的c++編譯器,只是單純把c++代碼翻譯成純c代碼。 所以新功能還是可以用純c硬幹。只是代碼會很醜。 書裡面還寫了一段,純c模擬template的方法。(利用#define) 真華麗。 純C對於變數有三種記憶體配置方式 static stack heap 所以增加class之後,class也都支援三種方式。 而且Bjarne要求class記憶體配置要跟struct一模一樣。 先有private , public protected是比較晚加入的功能。 operator=容易造成暫存物件太多 例如這樣 string a,b,c,d; a = b+c+d; 當年就知道有這問題,只是拖到c++11才修正。 (利用新特性,右值參考) operator[]() Bjarne一開始就知道,很多人希望讀/寫需要分開處理。也曾經想過要增加新特性來分離 兩種情況。但是後來發現proxy class可解決此問題。所以最後不加新特性。 (有夠懶惰) 大家都知道garbag collection效率會比手動delete差。 所以Bjarne堅持,gc可以加入,但是不能強迫使用。 喜歡手動delete的人,可以繼續使用舊方式。 關閉gc之後,選擇手動delete。 那編出來的代碼效率,就要跟以前手動delete效率一模一樣。不可以有任何差異。 當然「選擇性」的gc是一個很困難的問題。20年後的今天還是沒加入。 set_new_handler 照理說每次new之後,都要檢查指標來確定new成功與否。 只是new使用的太頻繁,大家都很懶。所以Bjarne決定加入set_new_handler函式。 Bjarne認為平行運算還要20年才會普及。所以不願意加入平行運算功能。 (真的被他猜中了) 如果要加入,他建議使用函式庫,不須要增加新特性。 關鍵字盡量不要加太多。 例如說 int using(int namespace); 這個函式肯定編不過,因為using,namespace都是關鍵字。 所以刻意挑了using,而不是use。刻意挑了namspace,而不是scope 運氣不好的話,很多代碼要重寫。任何新關鍵字都要非常小心。 template 使用()作為括號是可以做的,編譯器沒有任何困難。 採用<>作為括號理由是,大家都覺得<>比較好閱讀。 vector<vector<int>> 兩個>>會誤判的問題,當年就知道了。 編譯器需要針對這點特殊處理。 函式加上template之後,函式回傳值也可能是未知的型別。 Bjarne希望有一種新的函式寫法,函式回傳值的聲明往後挪動。 這樣編譯器比較好寫。 到了C++11終於實現了 增加const,inline,template之後 完全不需要再用#define 而且新寫法效率一樣好。 try,catch,throw 增加三個關鍵字實在太多了。有考慮過刪除try。但發覺代碼很難閱讀。 ============================================================================== 一些沒採用的設計: contructor/destructor 原始設計是要求函式命名成new(),delete() class裡面有兩個特殊函式 call() return() 呼叫class裡面所有函式,都會先執行一次call(),再開始執行。 函式執行結束,會自動執行return()函式。 頗無聊的設計。 function overloading 原始設計要求,如果函式同名,參數不同。需要明確寫出overload關鍵字。 理由是擔心編譯器太難寫。 後來發覺自己想太多,所以也取消了。 禁止複製class 禁止在stack/heap裡面產生class 禁止class被繼承 這些都可以利用現有技術作到,不需要增加任何新特性。 Bjarne真的很懶...... 不過c++11還是新增了一點小設計,來輔助這些情況。 operator++ 最原始的版本沒有區分++在前面或是後面。 ++x; x++; 兩者都會呼叫到同個函式 有考慮過新增兩個關鍵字 prefix , postfix 也有考慮過 operator++() ++operator() 老實說我覺得++operator比較好 inherited 用來呼叫父層class的函式,就跟java的super關鍵字類似 但因為C++有多重繼承,所以inherited肯定不能用。 (C++呼叫父層class,必須明確寫出class的名字) 書裡也寫明。inherited機制可以利用typedef模擬。那就更不用加了。 include 有考慮過新增這個關鍵字,取代傳統的#include