推 loveme00835:執著於語法的差異, relationship 倒是忘得一乾二淨 04/09 02:39
※ 引述《Ebergies (火神)》之銘言:
: 這麼說好了,前文的 Header 大概如下
: // b.h
: class A;
: class B {
: A *obj_a;
: public:
: void do_something();
: A *do_something_with( A *a);
: };
: 你有幾點訴求
: 1) 效率
: 2) 可讀性
: 2.1) 典型的重複程式
: 2.2) 從介面來看, 傳址不改值 and 傳參考卻會改值, 呼叫端的閱讀也會不利
[deleted]
我對 reference 與 pointer 之爭沒興趣
但其實 A *obj_a 與 A obj_a 在閱讀的時候是有滿大的不同
class B {
A obj_a;
...
}
以上這種情況型塑的是很清楚的 B has-a A
obj_a 在 B object 建立時跟著被建立
而且在 B object 解構時跟著被解構
A *obj_a 呢?這可能性就很多了
它可能只是另一個生命週期與 B 完全無關的物件
也可能根本指向 NULL
所以如果要型塑 has-a 的關係
我會先使用 A obj_a 的方式
除非 compile 速度慢到讓人受不了再去用 pimpl 統一解決
: 好吧,最後談到效率
: 的確很多時候透過指標取值的效率會有點差異
: 但是或許還有另一點值得注意
: 就是複製整個複雜的 structure 遠比複製指標還慢
: 一般的情況下連 string 這種小東西都有人建議多使用 const string &s 取值了
: 而通常我們都能夠分辨哪些東西是夠小,夠常被存取的東西
: 哪些東西是很大,我們不常重複的存取整份資料的東西
: (Managed C++ 把它們分為 value class/ ref class)
: (或者你也可以用 struct 與 class 區分它們)
: 而就我的經驗,使用 pointer 的機會應該遠比直接存取變數情況要多得多
: 當然,那些情況使用 pointer 的效率比較好,程式碼也比較單純
: 尤其是在使用 vector 將你的 class 裝起來的時候
效率上來說
若把具有 has-a 關係的成員宣告為 pointer
代表你在建構式中需要呼叫 new 來為它配置記憶體
因此建構物件時會明顯比較慢
class B {
A* obj_a;
public:
B() : obj_a(new A) {}
~B() { delete obj_a; }
};
void foo()
{
B b; // 需額外執行一次 new
for(int i = 0; i < 10; ++i){ // 迴圈額外執行了十次 new
B b;
...
}
}
如果你把 obj_a 宣告為 A
這些 new 的時間成本都會消失
因為在 stack 上配置物件的空間基本上是零成本的
除非說 A 的建構式自己會去呼叫 new
另外如果 B has-a A object
那麼把 obj_a 宣告為指標並不能增加複製物件的效率
class B {
A* obj_a;
public:
void assign_a(A* obj) {
delete obj_a;
obj_a = obj; // 通常不能這樣寫
}
};
因為 B has-a A
意味著 B 在解構時也會負責把 obj_A 解構
因此在進行 assignment 時也要一併進行所有權的轉移
比如下列的 code 會造成 runtime error:
void foo(){
A some_obj;
B b;
b.assign_a(&some_obj);
};
所以你要嘛就是在 assign_a 裡面自己做一次 copy
不然就是在呼叫 assign_a 之前自己用 new 來複製一份
(不過第二個方法不好...誰知道 B 的解構式是不是用 delete 來解構 obj_a 呢?)
只要 B 與 A 的關係是 has-a
那針對 obj_a 的 assignment 是無法避免地要複製所有 A 的內容
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 118.168.87.243
※ 編輯: littleshan 來自: 118.168.87.243 (04/09 02:38)