[問題] 物件可否call by value?

看板C_and_CPP (C/C++)作者 (動き出す時間...)時間11年前 (2014/06/20 01:43), 11年前編輯推噓4(4020)
留言24則, 4人參與, 最新討論串1/1
開發平台(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

06/20 01:44, , 1F
當然可以, 只不過由於複製成本通常較 primitive 形態大
06/20 01:44, 1F

06/20 01:45, , 2F
所以一般不會用 call by value 傳進去
06/20 01:45, 2F

06/20 01:45, , 3F
另外你後面提的方法其實很接近一種叫做 RVO 的最佳化策略
06/20 01:45, 3F

06/20 01:46, , 4F
在有啟動 RVO 的時候, 編譯器會幫你把前一段程式變成後一段
06/20 01:46, 4F

06/20 01:47, , 5F
你寫的程式跟 RVO 的差別在於, RVO 會直接在 fun1 裡初始化
06/20 01:47, 5F

06/20 01:48, , 6F
那個外面的物件, 而你這段程式是初始化完了才傳參考進去
06/20 01:48, 6F

06/20 01:50, , 7F
關於 RVO 可看維基百科: http://ppt.cc/IOrL
06/20 01:50, 7F

06/20 01:51, , 8F
(註: RVO 是標準允許的最佳化, 即使可能因此不呼叫 ctor 等)
06/20 01:51, 8F

06/20 02:06, , 9F
物件用等號賦值或從函式以"值"返回時,都會呼叫
06/20 02:06, 9F

06/20 02:07, , 10F
copy constructor,你是指這個嗎?
06/20 02:07, 10F

06/20 09:28, , 11F
call by value要考慮shallow copy的問題,
06/20 09:28, 11F

06/20 09:29, , 12F
你的結構裡面要是有指標的話 很可能會拿到一個出了結構
06/20 09:29, 12F

06/20 09:29, , 13F
說錯 出了scope 就無效的指標
06/20 09:29, 13F

06/20 09:30, , 14F
其實我個人認為copy by value在某些層面上是個危險動作
06/20 09:30, 14F

06/20 09:30, , 15F
除非你能非常有把握的處理掉shallow copy造成的無效指標
06/20 09:30, 15F

06/20 09:31, , 16F
而把結構hold住的指標全部改成shared_ptr可以降低風險
06/20 09:31, 16F

06/20 09:32, , 17F
但是deep copy會演變成一個recursive copy的問題就是
06/20 09:32, 17F

06/20 09:33, , 18F
總之 我認為你可能沒想到那麼多,除非有必要否則多半還
06/20 09:33, 18F

06/20 09:34, , 19F
是儘量避免對結構by value的方式會比較好
06/20 09:34, 19F

06/20 09:37, , 20F
傳物件時,需要考慮一下是否其實是move語意
06/20 09:37, 20F

06/20 10:38, , 21F
或者你應該仔細分析 fun1() 做的是不是 ctor 在做的工
06/20 10:38, 21F

06/20 10:38, , 22F
作,如果是,那應該把程式碼放在 ctor 裡。
06/20 10:38, 22F

06/20 10:39, , 23F
如果不是,也許應該變成 member function 做一些操作
06/20 10:39, 23F

06/20 10:39, , 24F
的前置動作(非初始化)
06/20 10:39, 24F
謝謝各位! 我想的到不要用call by value的原因是效率問題, 但沒考量到如果物件裡面有指標,call by value確實可能有危險。 感謝各位高手的提點^^ ※ 編輯: Keitaro (114.43.193.222), 06/24/2014 22:48:04
文章代碼(AID): #1Jeo4p-c (C_and_CPP)
文章代碼(AID): #1Jeo4p-c (C_and_CPP)