Re: [問題] C++ 不能像 Java 一樣,完全避掉 pointe …
※ 引述《eliang ()》之銘言:
: 我自己在寫程式的時候, 對於 reference 和 pointer 的選擇方式是:
: 「盡量使用 reference, 不能用 reference 時才用 pointer」
這是個好習慣。不過個人的建議是,在 C++ 中,最好是把兩者都當作
基本語彙,不要刻意去避免而扭曲語法,自然就好。
舉個例子:
X *p = new X;
你也可以寫成
X &r = *new X;
但後者並沒有什麼好處。
: 可是這樣會造成整體不一致, 因為有地方用 reference, 有地方用 pointer,
: 寫程式時常常會搞不清楚當初宣告的型別是什麼, 而要回頭去查前面的程式碼,
一些 IDE 或編程環境可以輔助這個問題,不過「回頭查」並沒有麻煩到哪裏去。
以介面設計來說,傳遞(參數或回傳值)reference 或 pointer 的取捨,主要
考量在於其值是否可能為 Null,如果有可能為 Null 就用 pointer,反之則用
reference,例如:
struct C1
{
C1(X const * =0); // 建立 C1 物件可要可不要某個 pointer to X 物件
...
};
struct C2
{
C2(Y const &); // 建立 C2 物件必須參照某個 Y 物件
...
};
X *fooX(); // fooX 可能回傳空值
Y &fooY(); // fooY 回傳某個 reference to Y 物件
: 想學 Java 完全都使用 reference 也不行, 因為以下用法都不合法:
: int& a[10]; // 10 個 int 的 reference, 可以分別參考 10 個 int
: vector<int&> b; // 元素為 int& 的動態陣列
: 結論是:
: reference 和 pointer 混用 -> 一致性差, 造成寫程式不方便
: 完全使用 reference -> 行不通
: 那麼是不是乾脆一律用 pointer 還比較好?
: 請問大家是怎麼選擇的?
有兩點應該要澄清。
首先,reference 和 pointer 不僅在語法上和語意上有所不同(主要差別在
於 pointer 帶有變量的特性),例如前面的例子,所以何來「一致性差」的
問題?大約只能說,reference 在某些情況下可以取代 pointer,而當兩者都
適用時,reference 的語意範圍較窄,且在語法上比較簡潔,因而在此情況下
「儘量用 reference」是好習慣。
(X & 的語意近似 X * const,也就是捨棄 pointer 帶有變量的特性,且在
建立時,就必須完成初始化的動作;當然細微處仍有不同,例如 X * const
可以接受 0 值讓其他模組作檢查。語法上則自然以 reference 較簡潔。)
其次,C++ reference 和 pointer 的機制,在內部都有額外的配置耗用,所以:
void foo(X);
void foo(X const &);
void foo(X const *);
以上三種寫法,如果 X 是某個 sizeof 不大於指標所佔空間的基本型別(例如
int),寫成後兩種並不會比第一種更有效率,所以某些講求效能的程式庫,其
所提供的 template 代碼,還會提供靜態型別選擇的機制,來作為優化(當 X
是基本型別用第一種,否則用第二種)。
同理,Java 的設計也一樣,它針對基本型別,例如 int,和 C++ 一樣是採取
「傳值」的語意,也就是在參數或回傳值傳遞時,是會自動產生一個複本的。
只有對使用者自訂型別,是採取內建式的「reference」語意。(並非如你所謂
的「Java 完全使用 reference」)
所以,假如 X 的型別是 int 的話,寫 vector<X &> 不如直接寫成 vector<X>
,後者不但簡潔,執行效率還比較快。
當然 vector<X&> 是錯的,當 X 不是基本型別時,為了效率考量,在 C++ 中
一般是用 vector<X*> 來取代;或者透過一個代理類別:
class X { ... };
typedef boost::shared_ptr<X> XRef;
接下來使用 vector<XRef>,就和 Java 的慣用法差不多了。
至於 Array,也是透過一個代理容器:
boost::shared_array<X> Array(new X[n]);
好處是在多數場合(尤其是 sizeof(X) / sizeof(XRef) 比值不大時),效率上
比 vector<XRef> 佔優勢。(但 vector 優點在於彈性和延伸性)
但總之,不論 Java 內部是怎麼實現的,也不可能會是:
X &x[n] 或 vector<X &> 這種東西。
C/C++ 遵循「傳值」語意,使用 pointer 或 reference 由用戶自決;Java 的
reference 語意是內建設施(但不包括基本型別),用戶是沒得選的。
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 59.120.214.120
※ 編輯: cppOrz 來自: 59.120.214.120 (11/26 05:15)
推
11/26 16:00, , 1F
11/26 16:00, 1F
討論串 (同標題文章)
完整討論串 (本文為第 2 之 2 篇):
C_and_CPP 近期熱門文章
PTT數位生活區 即時熱門文章