推 renderer:推 Orz大實在太熱心了 61.222.148.171 08/23
→ renderer:另外 cppOrz 唸起來真是帥呀 XD 61.222.148.171 08/23
→ renderer:cppOrz 看起來也是很可愛 XD 61.222.148.171 08/23
→ renderer:真有你的 呵呵 61.222.148.171 08/23
推 FRAXIS:A0版本最好可以加上const 不然常數不能加 140.119.162.51 08/23
→ FRAXIS:return by value 不一定需要加上const 140.119.162.51 08/23
推 khoguan:改取了這種id,舒緩了您嚴謹深入的高人風貌 :-)220.130.208.168 08/23
推 drkkimo:@@? 218.164.26.249 08/23
推 drkkimo:我覺得分析的很詳細 多幾篇這類的探討真不錯 218.164.26.249 08/23
推 sekya:好文 必推一下 59.104.35.45 08/25
> -------------------------------------------------------------------------- <
作者: renderer (rendering) 看板: C_and_CPP
標題: Re: [心得] operator+ 與 operator+= 的設計
時間: Tue Aug 23 12:00:41 2005
※ 引述《cppOrz (cppOrz)》之銘言:
: Point const operator+(Point const &lhs, Point const &rhs) // 版本 A1
: {
: return Point(lhs.x+rhs.x, lhs.y+rhs.y);
: }
: Point const operator+(Point const &lhs, Point const &rhs) // 版本 A2
: {
: return Point(lhs) += rhs; // 利用版本 B2
: }
敢問 cppOrz 大
版本 A1 與 A2 是否有效能上的差異呢
------------------------------------------------
cpp Orz - 面對 cpp Orz
太可愛了 呵呵
別打我 ...
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 61.222.148.171
※ 編輯: renderer 來自: 61.222.148.171 (08/23 12:02)
→ cppOrz:這可考倒我了,我覺得應該是一樣啦,就算有差也 59.120.214.120 08/23
→ cppOrz:差不到哪裏去。不過利用 += 的實作是維持一致性 59.120.214.120 08/23
→ cppOrz:的原則,應該比較好。 59.120.214.120 08/23
> -------------------------------------------------------------------------- <
作者: khoguan (Khoguan Phuann) 看板: C_and_CPP
標題: Re: [心得] operator+ 與 operator+= 的設計
時間: Tue Aug 23 13:02:53 2005
※ 引述《renderer (rendering)》之銘言:
: ※ 引述《cppOrz (cppOrz)》之銘言:
: : Point const operator+(Point const &lhs, Point const &rhs) // 版本 A1
: : {
: : return Point(lhs.x+rhs.x, lhs.y+rhs.y);
: : }
: : Point const operator+(Point const &lhs, Point const &rhs) // 版本 A2
: : {
: : return Point(lhs) += rhs; // 利用版本 B2
: : }
: 敢問 cppOrz 大
: 版本 A1 與 A2 是否有效能上的差異呢
: → cppOrz:這可考倒我了,我覺得應該是一樣啦,就算有差也 59.120.214.120 08/23
: → cppOrz:差不到哪裏去。不過利用 += 的實作是維持一致性 59.120.214.120 08/23
: → cppOrz:的原則,應該比較好。 59.120.214.120 08/23
除了 cppOrz大大的推文說明外,我想,版本A1有個大問題是,
它往往要指定成 friend function 才能存取到 Point class的
private data member, 雖然很多時候,像是 Point 這種 class,
都會提供 public 的 getter member function, 但也有其他時候
是沒有提供的。而版本 A2 利用既有的public operator+= 來實作
operator+ 就可完全避免這種問題。所以不但維持了一致性,也可
保有較佳的封裝性。
題外話,在幾何上「兩點相加」這樣的概念存在嗎?可以表示位移嗎?
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.130.208.168
→ cppOrz:兩點相加當然是沒有的,但是 (x,y) 數對除了可以 59.120.214.120 08/23
→ cppOrz:看成一個點之外,也可以看成一個向量,所以加法 59.120.214.120 08/23
→ cppOrz:仍是有用的。不過我主要是示範用偷懶的例子啦 59.120.214.120 08/23
→ cppOrz:另外,如果必要的話,設成 friend 算正常的。 59.120.214.120 08/23
> -------------------------------------------------------------------------- <
作者: renderer (rendering) 看板: C_and_CPP
標題: Re: [心得] operator+ 與 operator+= 的設計
時間: Tue Aug 23 14:36:56 2005
※ 引述《renderer (rendering)》之銘言:
: 標題: Re: [心得] operator+ 與 operator+= 的設計
: 時間: Tue Aug 23 12:00:41 2005
: ※ 引述《cppOrz (cppOrz)》之銘言:
: : Point const operator+(Point const &lhs, Point const &rhs) // 版本 A1
: : {
: : return Point(lhs.x+rhs.x, lhs.y+rhs.y);
: : }
: : Point const operator+(Point const &lhs, Point const &rhs) // 版本 A2
: : {
: : return Point(lhs) += rhs; // 利用版本 B2
: : }
: 敢問 cppOrz 大
: 版本 A1 與 A2 是否有效能上的差異呢
:
: --
: ※ 發信站: 批踢踢實業坊(ptt.cc)
: ◆ From: 61.222.148.171
: ※ 編輯: renderer 來自: 61.222.148.171 (08/23 12:02)
: → cppOrz:這可考倒我了,我覺得應該是一樣啦,就算有差也 59.120.214.120 08/23
: → cppOrz:差不到哪裏去。不過利用 += 的實作是維持一致性 59.120.214.120 08/23
: → cppOrz:的原則,應該比較好。 59.120.214.120 08/23
其實我真正想問的是 A2 版本的 RVO 是否仍然會作用
A2 版本如果 RV0 沒有作用 就會多一次物件建構的成本了
當然 這種效能上的差異是雞蛋裏挑骨頭
我有試了一下 struct Vector { float x,y,z }; 在兩個實作間的效能差異
似乎 A2 會比較慢些
(GCC 最佳化全開)
另外問一個問題是:
一個 inline 函式裏又呼叫了另一個 inline 函式
編譯器是否會捨棄 inline 呢 會以什麼為決擇依據呢
感謝 :)
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 61.222.148.171
→ renderer:嘿嘿 在沒有新手發問的時候 多跟高手們討點寶 61.222.148.171 08/23
> -------------------------------------------------------------------------- <
作者: FRAXIS (喔喔) 看板: C_and_CPP
標題: Re: [心得] operator+ 與 operator+= 的設計
時間: Tue Aug 23 16:03:15 2005
※ 引述《cppOrz (cppOrz)》之銘言:
: 其實我一般是不加 const 的,不過 Effective C++ 系列中把回傳值加上
: 了 const,所以就照著寫。書上的理由是,如果不加 const,以下的寫法
: 是可以通過編譯的:
:
: Point a, b, c;
: (a+b) = c; // 竟然可以這樣寫!
:
: 加上 const 就不會有這種問題了。
:
: --
: ※ 發信站: 批踢踢實業坊(ptt.cc)
: ◆ From: 59.120.214.120
: 推 jeunder:你誤會他的意思了, 他是說 operator+ function 61.64.150.151 08/23
: → jeunder:最好要設成 const function... 61.64.150.151 08/23
: → jeunder:否則面對 const instance 時, 無法加起來... 61.64.150.151 08/23
: → cppOrz:感謝指正。我從來不寫 A0 版本所以沒注意到這問 59.120.214.120 08/23
: → cppOrz:題,不過 return const 物件是照書上的說明 59.120.214.120 08/23
cppOrz大大沒有誤會我的意思啦,因為我兩句推文分別講兩件事情
,分別是const function和return const的事情。
我可以理解Effective C++作者的想法(a+b) = c是件很怪的事情。
但是如果有一個成員函式f,他並非const的成員函式,假使return value
非const的話,我可以這樣寫
Point t1, t2, t3, t4;
Point t3 = (t1 + t2).f() + (t3 + t4).f();
然而假使return value是const的話,寫起來就比較麻煩。
這沒有什麼對錯的問題,只是設計理念和習慣問題而已..
--
我記得好像Herb Sutter的新書有討論到這問題,有人有印象嘛?
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 61.229.34.163
推 jeunder:對於 const instance 施行 nonconst mem. func. 61.64.150.151 08/23
→ jeunder:根本就是件很奇怪的事情... 61.64.150.151 08/23
> -------------------------------------------------------------------------- <
作者: UNARYvvv (有趣生活) 看板: C_and_CPP
標題: Re: [心得] operator+ 與 operator+= 的設計
時間: Wed Aug 24 12:57:35 2005
※ 引述《renderer (rendering)》之銘言:
: ※ 引述《renderer (rendering)》之銘言:
: : 標題: Re: [心得] operator+ 與 operator+= 的設計
: : 時間: Tue Aug 23 12:00:41 2005
: : 敢問 cppOrz 大
: : 版本 A1 與 A2 是否有效能上的差異呢
: : --
: : ◆ From: 61.222.148.171
: : → cppOrz:這可考倒我了,我覺得應該是一樣啦,就算有差也 59.120.214.120 08/23
: : → cppOrz:差不到哪裏去。不過利用 += 的實作是維持一致性 59.120.214.120 08/23
: : → cppOrz:的原則,應該比較好。 59.120.214.120 08/23
: 其實我真正想問的是 A2 版本的 RVO 是否仍然會作用
^喔?
: A2 版本如果 RV0 沒有作用 就會多一次物件建構的成本了
^零!?
r大..我彷彿看見了你的惡搞XDD
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 61.70.137.117
推 renderer:o.O 61.222.148.171 08/24
推 ledia:怎麼會看出來 @_@? 話說 O 和 0 是會打錯的 XD 140.112.30.55 08/24
推 renderer:U大 您不會連 BBS 都用 Programming Font 吧 XD 61.222.148.171 08/24
→ renderer:0.0 O.O 61.222.148.171 08/24
推 UNARYvvv:我是用 PCMan 原本設定啊..細明體囉~ 61.70.137.117 08/24
推 renderer:那 U大眼力好 61.222.148.171 08/24
> -------------------------------------------------------------------------- <
作者: cppOrz (cppOrz) 看板: C_and_CPP
標題: [心得] operator+ 與 operator+= 的設計
時間: Tue Aug 23 11:30:26 2005
我換了一個新的帳號: gocpp -> cppOrz
因為新的帳號實在是太可愛了!
這篇的內容是有關 operator overloading 設計的觀念
假如有個 class Point 如下:
struct Point
{
Point(int a=0, int b=0) : x(a), y(b) {}
int x, y;
};
現在想替它寫個 operator+ 運算子,該怎麼辦呢?
Point const Point::operator+(Point const &rhs) // 版本 A0
{
return Point(x+rhs.x, y+rhs.y);
}
版本 A0 是常見的作法,但是它其實不太好,有兩個主要的缺點。
一個是介面設計上的,一個是實作方法上的。首先看介面設計的
問題,把 operator+ 當作成員函式的話,+ 號的左邊就不能隱式
轉型,也就是如果某個型別 T 可以隱式轉型成 Point 的話,那
就會出現下面的狀況:
Point p1;
T p2;
Point p;
p = p1 + p2; // ok, 沒問題
p = p2 + p1; // 喔噢,編譯不過。
通常的情況, 加法運算應該是要滿足交換率的。至少 C/C++ 的內建
型別無不如此。但這種設計卻不符合需求,因此必須改良一下。
Point const operator+(Point const &lhs, Point const &rhs) // 版本 A1
{
return Point(lhs.x+rhs.x, lhs.y+rhs.y);
}
把 operator+ 這種二元運算,設為 namespace 層級(而非 class
成員)的函式,是 C++ 函式介面設計的基本觀念,大家如果有注意到
的話,看一下 std::complex<T> 的介面,它就是這樣設計的。這樣不
論左邊或右邊兩個參數都允許隱式轉型。
我印象中 C# 的 operator overloading 介面,就和 C++ 不同,例如
它的 operator+,這種二元運算,仍是設計為成員函式,而且還會幫用
戶自動產生相關的運算,產生規則和實作的方式也和 C++ 標準的做法
不同。
版本 A1 的介面雖然理想了,但它的實作方式卻仍然存在缺陷。原因是,
如果我們想要替 class Point 增加一個 operator+= 的成員,那該怎
麼辦呢?
Point &Point::operator+=(Point const &rhs) // 版本 B1
{
return *this = *this + rhs; // 利用版本 A1
}
初看起來它很完美,沒有什麼問題,但實際上這種設計在 C++ 中可能會
造成效率的損失。原因在於 operator+= 回傳的是 reference to *this,
但其中的過程卻是呼叫了 operator+,而 operator+ 回傳的是物件,也
就是經過了一次不必要的物件複製的動作。(我印象中,C# 自動生成的
程式碼就是類似這樣做的,不過不同的是,C# 有內建 GC,回傳值可以用
new的,不必擔心物件複製的問題。)因為本來 operator+= 完全是不需
要物件複製的:
Point &Point::operator+=(Point const &rhs) // 版本 B2
{
x += rhs.x;
y += rhs.y;
return *this;
}
可以看出,版本 B1 的實作,多了一次不必要的物件複製,而且由於
它是將結果存到 *this 中,RVO(回傳值優化)的編譯器技術也無用
武之地。像 class Point 這樣的小東西,多產生一個暫時物件的差
別幾乎可以視而不見,但若是某些大型架構,例如多維的 Matrix
運算,而且是大量的頻繁使用時,每次多一個暫時物件,整體效率的
損失就很可觀了。
因此,正確的實作法應該是以 operator+= 來實現 operator+
Point const operator+(Point const &lhs, Point const &rhs) // 版本 A2
{
return Point(lhs) += rhs; // 利用版本 B2
}
另外,以上的例子,也告訴我們一件事,就是以下兩種寫法:
Point a, b, c, d;
Point p1 = a + b + c + d;
Point p2 = a;
p2 += b;
p2 += c;
p2 += d;
使用 p2 的方式,會比 p1 來得有效率,所以如果有嚴格的效率
要求時,最好多用 p2 的寫法。
兩個重點:
一、關於介面,不要把 operator+ 設計為成員函式,它應該是個
namespace 函式
二、關於實作,請以 operator+= 來實現 operator+(不要倒過來),
因為後者多了一次物件複製。
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 59.120.214.120
推 renderer:推 Orz大實在太熱心了 61.222.148.171 08/23
→ renderer:另外 cppOrz 唸起來真是帥呀 XD 61.222.148.171 08/23
→ renderer:cppOrz 看起來也是很可愛 XD 61.222.148.171 08/23
→ renderer:真有你的 呵呵 61.222.148.171 08/23
推 FRAXIS:A0版本最好可以加上const 不然常數不能加 140.119.162.51 08/23
→ FRAXIS:return by value 不一定需要加上const 140.119.162.51 08/23
推 khoguan:改取了這種id,舒緩了您嚴謹深入的高人風貌 :-)220.130.208.168 08/23
推 drkkimo:@@? 218.164.26.249 08/23
推 drkkimo:我覺得分析的很詳細 多幾篇這類的探討真不錯 218.164.26.249 08/23
推 sekya:好文 必推一下 59.104.35.45 08/25
> -------------------------------------------------------------------------- <
作者: renderer (rendering) 看板: C_and_CPP
標題: Re: [心得] operator+ 與 operator+= 的設計
時間: Tue Aug 23 12:00:41 2005
※ 引述《cppOrz (cppOrz)》之銘言:
: Point const operator+(Point const &lhs, Point const &rhs) // 版本 A1
: {
: return Point(lhs.x+rhs.x, lhs.y+rhs.y);
: }
: Point const operator+(Point const &lhs, Point const &rhs) // 版本 A2
: {
: return Point(lhs) += rhs; // 利用版本 B2
: }
敢問 cppOrz 大
版本 A1 與 A2 是否有效能上的差異呢
------------------------------------------------
cpp Orz - 面對 cpp Orz
太可愛了 呵呵
別打我 ...
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 61.222.148.171
※ 編輯: renderer 來自: 61.222.148.171 (08/23 12:02)
→ cppOrz:這可考倒我了,我覺得應該是一樣啦,就算有差也 59.120.214.120 08/23
→ cppOrz:差不到哪裏去。不過利用 += 的實作是維持一致性 59.120.214.120 08/23
→ cppOrz:的原則,應該比較好。 59.120.214.120 08/23
> -------------------------------------------------------------------------- <
作者: khoguan (Khoguan Phuann) 看板: C_and_CPP
標題: Re: [心得] operator+ 與 operator+= 的設計
時間: Tue Aug 23 13:02:53 2005
※ 引述《renderer (rendering)》之銘言:
: ※ 引述《cppOrz (cppOrz)》之銘言:
: : Point const operator+(Point const &lhs, Point const &rhs) // 版本 A1
: : {
: : return Point(lhs.x+rhs.x, lhs.y+rhs.y);
: : }
: : Point const operator+(Point const &lhs, Point const &rhs) // 版本 A2
: : {
: : return Point(lhs) += rhs; // 利用版本 B2
: : }
: 敢問 cppOrz 大
: 版本 A1 與 A2 是否有效能上的差異呢
: → cppOrz:這可考倒我了,我覺得應該是一樣啦,就算有差也 59.120.214.120 08/23
: → cppOrz:差不到哪裏去。不過利用 += 的實作是維持一致性 59.120.214.120 08/23
: → cppOrz:的原則,應該比較好。 59.120.214.120 08/23
除了 cppOrz大大的推文說明外,我想,版本A1有個大問題是,
它往往要指定成 friend function 才能存取到 Point class的
private data member, 雖然很多時候,像是 Point 這種 class,
都會提供 public 的 getter member function, 但也有其他時候
是沒有提供的。而版本 A2 利用既有的public operator+= 來實作
operator+ 就可完全避免這種問題。所以不但維持了一致性,也可
保有較佳的封裝性。
題外話,在幾何上「兩點相加」這樣的概念存在嗎?可以表示位移嗎?
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.130.208.168
→ cppOrz:兩點相加當然是沒有的,但是 (x,y) 數對除了可以 59.120.214.120 08/23
→ cppOrz:看成一個點之外,也可以看成一個向量,所以加法 59.120.214.120 08/23
→ cppOrz:仍是有用的。不過我主要是示範用偷懶的例子啦 59.120.214.120 08/23
→ cppOrz:另外,如果必要的話,設成 friend 算正常的。 59.120.214.120 08/23
> -------------------------------------------------------------------------- <
作者: renderer (rendering) 看板: C_and_CPP
標題: Re: [心得] operator+ 與 operator+= 的設計
時間: Tue Aug 23 14:36:56 2005
※ 引述《renderer (rendering)》之銘言:
: 標題: Re: [心得] operator+ 與 operator+= 的設計
: 時間: Tue Aug 23 12:00:41 2005
: ※ 引述《cppOrz (cppOrz)》之銘言:
: : Point const operator+(Point const &lhs, Point const &rhs) // 版本 A1
: : {
: : return Point(lhs.x+rhs.x, lhs.y+rhs.y);
: : }
: : Point const operator+(Point const &lhs, Point const &rhs) // 版本 A2
: : {
: : return Point(lhs) += rhs; // 利用版本 B2
: : }
: 敢問 cppOrz 大
: 版本 A1 與 A2 是否有效能上的差異呢
:
: --
: ※ 發信站: 批踢踢實業坊(ptt.cc)
: ◆ From: 61.222.148.171
: ※ 編輯: renderer 來自: 61.222.148.171 (08/23 12:02)
: → cppOrz:這可考倒我了,我覺得應該是一樣啦,就算有差也 59.120.214.120 08/23
: → cppOrz:差不到哪裏去。不過利用 += 的實作是維持一致性 59.120.214.120 08/23
: → cppOrz:的原則,應該比較好。 59.120.214.120 08/23
其實我真正想問的是 A2 版本的 RVO 是否仍然會作用
A2 版本如果 RV0 沒有作用 就會多一次物件建構的成本了
當然 這種效能上的差異是雞蛋裏挑骨頭
我有試了一下 struct Vector { float x,y,z }; 在兩個實作間的效能差異
似乎 A2 會比較慢些
(GCC 最佳化全開)
另外問一個問題是:
一個 inline 函式裏又呼叫了另一個 inline 函式
編譯器是否會捨棄 inline 呢 會以什麼為決擇依據呢
感謝 :)
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 61.222.148.171
→ renderer:嘿嘿 在沒有新手發問的時候 多跟高手們討點寶 61.222.148.171 08/23
> -------------------------------------------------------------------------- <
作者: FRAXIS (喔喔) 看板: C_and_CPP
標題: Re: [心得] operator+ 與 operator+= 的設計
時間: Tue Aug 23 16:03:15 2005
※ 引述《cppOrz (cppOrz)》之銘言:
: 其實我一般是不加 const 的,不過 Effective C++ 系列中把回傳值加上
: 了 const,所以就照著寫。書上的理由是,如果不加 const,以下的寫法
: 是可以通過編譯的:
:
: Point a, b, c;
: (a+b) = c; // 竟然可以這樣寫!
:
: 加上 const 就不會有這種問題了。
:
: --
: ※ 發信站: 批踢踢實業坊(ptt.cc)
: ◆ From: 59.120.214.120
: 推 jeunder:你誤會他的意思了, 他是說 operator+ function 61.64.150.151 08/23
: → jeunder:最好要設成 const function... 61.64.150.151 08/23
: → jeunder:否則面對 const instance 時, 無法加起來... 61.64.150.151 08/23
: → cppOrz:感謝指正。我從來不寫 A0 版本所以沒注意到這問 59.120.214.120 08/23
: → cppOrz:題,不過 return const 物件是照書上的說明 59.120.214.120 08/23
cppOrz大大沒有誤會我的意思啦,因為我兩句推文分別講兩件事情
,分別是const function和return const的事情。
我可以理解Effective C++作者的想法(a+b) = c是件很怪的事情。
但是如果有一個成員函式f,他並非const的成員函式,假使return value
非const的話,我可以這樣寫
Point t1, t2, t3, t4;
Point t3 = (t1 + t2).f() + (t3 + t4).f();
然而假使return value是const的話,寫起來就比較麻煩。
這沒有什麼對錯的問題,只是設計理念和習慣問題而已..
--
我記得好像Herb Sutter的新書有討論到這問題,有人有印象嘛?
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 61.229.34.163
推 jeunder:對於 const instance 施行 nonconst mem. func. 61.64.150.151 08/23
→ jeunder:根本就是件很奇怪的事情... 61.64.150.151 08/23
> -------------------------------------------------------------------------- <
作者: UNARYvvv (有趣生活) 看板: C_and_CPP
標題: Re: [心得] operator+ 與 operator+= 的設計
時間: Wed Aug 24 12:57:35 2005
※ 引述《renderer (rendering)》之銘言:
: ※ 引述《renderer (rendering)》之銘言:
: : 標題: Re: [心得] operator+ 與 operator+= 的設計
: : 時間: Tue Aug 23 12:00:41 2005
: : 敢問 cppOrz 大
: : 版本 A1 與 A2 是否有效能上的差異呢
: : --
: : ◆ From: 61.222.148.171
: : → cppOrz:這可考倒我了,我覺得應該是一樣啦,就算有差也 59.120.214.120 08/23
: : → cppOrz:差不到哪裏去。不過利用 += 的實作是維持一致性 59.120.214.120 08/23
: : → cppOrz:的原則,應該比較好。 59.120.214.120 08/23
: 其實我真正想問的是 A2 版本的 RVO 是否仍然會作用
^喔?
: A2 版本如果 RV0 沒有作用 就會多一次物件建構的成本了
^零!?
r大..我彷彿看見了你的惡搞XDD
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 61.70.137.117
推 renderer:o.O 61.222.148.171 08/24
推 ledia:怎麼會看出來 @_@? 話說 O 和 0 是會打錯的 XD 140.112.30.55 08/24
推 renderer:U大 您不會連 BBS 都用 Programming Font 吧 XD 61.222.148.171 08/24
→ renderer:0.0 O.O 61.222.148.171 08/24
推 UNARYvvv:我是用 PCMan 原本設定啊..細明體囉~ 61.70.137.117 08/24
推 renderer:那 U大眼力好 61.222.148.171 08/24
> -------------------------------------------------------------------------- <
作者: cppOrz (cppOrz) 看板: C_and_CPP
標題: [心得] oprator+ 兩種版本效能測試報告
時間: Wed Aug 24 09:17:55 2005
為了驗證 operator+ 的實作效能,特別寫了幾段小程式測試
struct X
{
int val[1000];
X &operator+=(X const &rhs)
{
for (int i=0; i<1000; ++i) { val[i] += rhs.val[i]; }
return *this;
}
};
X const operator+(X const &lhs, X const &rhs) // 版本 X1
{
return X(lhs) += rhs;
}
X const operator+(X const &lhs, X const &rhs) // 版本 X2
{
X t;
for (int i=0; i<1000; ++i) { t.val[i] = lhs.val[i] + rhs.val[i]; }
return t;
}
void Test1() // 測試程式,做 20 萬次加法運算
{
for (int i=0; i<200000; ++i) { X a, b, c; c = a+b; }
}
平均執行效率如下:(以下時間單位為 Ticks)
版本 X1 版本 X2
VC6(D) 3390 2578
VC6(R) 1250 750
g++3.4.2(D) 1984 1891
BCC5.6.4(D) 1394 1594
BCC5.6.4(R) 672 690
其中(D) 是 Debug 版,(R)是 Release 版,但我想還是以 Debug 版為主,
因為 Release 版做的一些優化說不定把某些動作省略了。
所以主要比較的還是 X1 和 X2 之間的差距,VC 的結果是 X2 明顯優勢,
BCC是 X1 優勢,g++ 是差不多,X2 稍好。也就是說 VC6 的 RVO 技術可
能做得不是挺好才會這樣(因為即使 Release 版也是 X2 明顯優勢)
又,感覺 BCB 的 RVO 是最厲害的,對暫時物件的優化處理向來是 Borland
的專長。
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 59.120.214.120
※ 編輯: cppOrz 來自: 59.120.214.120 (08/24 09:19)
推 renderer:感謝 cppOrz 的測試 61.222.148.171 08/24
※ 編輯: cppOrz 來自: 59.120.214.120 (08/24 10:10)
> -------------------------------------------------------------------------- <
作者: khoguan (Khoguan Phuann) 看板: C_and_CPP
標題: Re: [心得] oprator+ 兩種版本效能測試報告
時間: Wed Aug 24 10:19:52 2005
※ 引述《cppOrz (cppOrz)》之銘言:
: 為了驗證 operator+ 的實作效能,特別寫了幾段小程式測試
[...]
: X const operator+(X const &lhs, X const &rhs) // 版本 X1
: {
: return X(lhs) += rhs;
: }
: X const operator+(X const &lhs, X const &rhs) // 版本 X2
: {
: X t;
: for (int i=0; i<1000; ++i) { t.val[i] = lhs.val[i] + rhs.val[i]; }
: return t;
: }
: void Test1() // 測試程式,做 20 萬次加法運算
: {
: for (int i=0; i<200000; ++i) { X a, b, c; c = a+b; }
要測 RVO 的話,可能要用 X c = a + b; 來測會比較好一點。
讓 compiler 比較容易直接拿 a + b 的結果來建構 c,達到
RVO 的效果,省了中間建構暫時物件的手續。
若用 X c; 然後再 c = a + b; 的話,因為 c 物件已經事先建立起來,
再 c = a + b; 語意上得要另行呼叫 c 物件的 copy assignment operator,
這種操作和 RVO 所要簡省的建構物件的操作是不同類的,因此
compiler 就比較不可能為它最佳化。
: }
[...]
: 所以主要比較的還是 X1 和 X2 之間的差距,VC 的結果是 X2 明顯優勢,
: BCC是 X1 優勢,g++ 是差不多,X2 稍好。也就是說 VC6 的 RVO 技術可
: 能做得不是挺好才會這樣(因為即使 Release 版也是 X2 明顯優勢)
: 又,感覺 BCB 的 RVO 是最厲害的,對暫時物件的優化處理向來是 Borland
: 的專長。
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.130.208.168
※ 編輯: khoguan 來自: 220.130.208.168 (08/24 10:28)
推 khoguan:不好意思,我是不是修掉了人家的推文?220.130.208.168 08/24
推 cppOrz:我的不見了啦~~ 59.120.214.120 08/24
→ cppOrz:還是可以做 RVO,主要是因為我要讓 X1, X2, Y 的 59.120.214.120 08/24
→ cppOrz:測試條件一樣,又懶得幫 Y 加 copy ctor 59.120.214.120 08/24
※ 編輯: khoguan 來自: 220.130.208.168 (08/24 11:38)
→ freaky:VC7.1 和 VC8 debug 版本 2766(X1) vs 2578(X2) 203.70.36.38 08/24
→ freaky:release版本 0(X1) vs 234(X2) 203.70.36.38 08/24
> -------------------------------------------------------------------------- <
作者: khoguan (Khoguan Phuann) 看板: C_and_CPP
標題: Re: [心得] oprator+ 兩種版本效能測試報告
時間: Wed Aug 24 12:15:59 2005
※ 引述《khoguan (Khoguan Phuann)》之銘言:
: ※ 引述《cppOrz (cppOrz)》之銘言:
: : 為了驗證 operator+ 的實作效能,特別寫了幾段小程式測試
: [...]
: : X const operator+(X const &lhs, X const &rhs) // 版本 X1
: : {
: : return X(lhs) += rhs;
: : }
: : X const operator+(X const &lhs, X const &rhs) // 版本 X2
: : {
: : X t;
: : for (int i=0; i<1000; ++i) { t.val[i] = lhs.val[i] + rhs.val[i]; }
: : return t;
: : }
: : void Test1() // 測試程式,做 20 萬次加法運算
: : {
: : for (int i=0; i<200000; ++i) { X a, b, c; c = a+b; }
: : }
: 要測 RVO 的話,可能要用 X c = a + b; 來測會比較好一點。
: 讓 compiler 比較容易直接拿 a + b 的結果來建構 c,達到
: RVO 的效果,省了中間建構暫時物件的手續。
: 若用 X c; 然後再 c = a + b; 的話,因為 c 物件已經事先建立起來,
: 再 c = a + b; 語意上得要另行呼叫 c 物件的 copy assignment operator,
: 這種操作和 RVO 所要簡省的建構物件的操作是不同類的,因此
: compiler 就比較不可能為它最佳化。
關於我上述論點,剛才我找到 Lippman 的文章,支持我的想法。
請參考:
http://www.awprofessional.com/articles/article.asp?p=25033&seqNum=3
和
http://www.awprofessional.com/articles/article.asp?p=25033&seqNum=4
他最後並根據同樣的理路,列出了兩種寫法:
第一種:
Matrix mat;
while ( something.more() )
{
mat = something.fetch_mat();
// do something with mat ...
}
第二種:
while ( something.more() )
{
Matrix mat = something.fetch_mat();
// do something with mat ...
}
並說第二種其實比較有效率。這兩種寫法,我之前也想到過,
但就是無法判斷到底哪一種比較好 :-)
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.130.208.168