看板 C_and_CPP 關於我們 聯絡資訊
開發平台(Platform): (Ex: VC++, GCC, Linux, ...) VC 額外使用到的函數庫(Library Used): (Ex: OpenGL, ...) None 問題(Question): 請問物件、結構等複合型態,可否call by value? 我知道這問題可能很基本,但我問了朋友跟同事,沒有人能給我一個肯定的答案, 所以還是厚著臉皮上來請教各位先進了。 因工作關係開始寫MFC,開始學著C++的物件怎麼用。 但我一直疑惑著,複合型態是否真的無法使用call by value呢? 我知道像是陣列、結構、物件這種複合型態,一般來說都call by pointer/reference。 而複合型態的名稱,等同於它在記憶體裡面的起使位置。 那麼,如果我碰到底下這種狀況 "在function call產生的複合型態物件,要回傳到主程式中" 此時我不能用call by pointer/reference, 因為程式一離開function,產生的物件就消失了。 所以我猜想是否能寫成改為call by value,像底下這樣... class CA; int main() { CA obj_A = fun1(); ... } CA fun1() { CA fun_obj = ... return fun_obj; } 我使用VC2008測試結果是可以的,結果正確。 那麼,complier是否在return物件時,把fun_obj的內容,完全拷貝給obj_A? 所以實際上,複合物件也是可以call by value? 當然我也想的到像這種情況,另一個作法是,先在main裡面把obj_A宣告, 然後用call by reference傳給fun1(), 使得fun1()直接將運算結果寫在obj_A的位址,改成像這樣... class CA; int main() { CA obj_A; fun1(obj_A); ... } void fun1(CA& fun_obj) { fun_obj=... } 但我想弄清楚,複合型態物件,其實是可以call by value的,是嗎? 謝謝各位。 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 114.43.213.130 ※ 文章網址: http://www.ptt.cc/bbs/C_and_CPP/M.1403199795.A.FA6.html
LPH66:當然可以, 只不過由於複製成本通常較 primitive 形態大 06/20 01:44
LPH66:所以一般不會用 call by value 傳進去 06/20 01:45
LPH66:另外你後面提的方法其實很接近一種叫做 RVO 的最佳化策略 06/20 01:45
LPH66:在有啟動 RVO 的時候, 編譯器會幫你把前一段程式變成後一段 06/20 01:46
LPH66:你寫的程式跟 RVO 的差別在於, RVO 會直接在 fun1 裡初始化 06/20 01:47
LPH66:那個外面的物件, 而你這段程式是初始化完了才傳參考進去 06/20 01:48
LPH66:關於 RVO 可看維基百科: http://ppt.cc/IOrL 06/20 01:50
LPH66:(註: RVO 是標準允許的最佳化, 即使可能因此不呼叫 ctor 等) 06/20 01:51
kkkmode:物件用等號賦值或從函式以"值"返回時,都會呼叫 06/20 02:06
kkkmode:copy constructor,你是指這個嗎? 06/20 02:07
Killercat:call by value要考慮shallow copy的問題, 06/20 09:28
Killercat:你的結構裡面要是有指標的話 很可能會拿到一個出了結構 06/20 09:29
Killercat:說錯 出了scope 就無效的指標 06/20 09:29
Killercat:其實我個人認為copy by value在某些層面上是個危險動作 06/20 09:30
Killercat:除非你能非常有把握的處理掉shallow copy造成的無效指標 06/20 09:30
Killercat:而把結構hold住的指標全部改成shared_ptr可以降低風險 06/20 09:31
Killercat:但是deep copy會演變成一個recursive copy的問題就是 06/20 09:32
Killercat:總之 我認為你可能沒想到那麼多,除非有必要否則多半還 06/20 09:33
Killercat:是儘量避免對結構by value的方式會比較好 06/20 09:34
loveme00835:傳物件時,需要考慮一下是否其實是move語意 06/20 09:37
loveme00835:或者你應該仔細分析 fun1() 做的是不是 ctor 在做的工 06/20 10:38
loveme00835:作,如果是,那應該把程式碼放在 ctor 裡。 06/20 10:38
loveme00835:如果不是,也許應該變成 member function 做一些操作 06/20 10:39
loveme00835:的前置動作(非初始化) 06/20 10:39
謝謝各位! 我想的到不要用call by value的原因是效率問題, 但沒考量到如果物件裡面有指標,call by value確實可能有危險。 感謝各位高手的提點^^ ※ 編輯: Keitaro (114.43.193.222), 06/24/2014 22:48:04