4 回答

TA貢獻(xiàn)1852條經(jīng)驗(yàn) 獲得超7個(gè)贊
C ++ 11的經(jīng)驗(yàn)法則:
通過(guò)按值時(shí),除
你不需要對(duì)象的所有權(quán)和一個(gè)簡(jiǎn)單的別名會(huì)做,在這種情況下你通過(guò)
const
引用傳遞,你必須改變對(duì)象,在這種情況下,使用非
const
左值引用傳遞,您將派生類的對(duì)象作為基類傳遞,在這種情況下,您需要通過(guò)引用傳遞。(使用以前的規(guī)則來(lái)確定是否通過(guò)
const
引用傳遞。)
幾乎從不建議通過(guò)指針傳遞??蛇x參數(shù)最好表示為a std::optional
(boost::optional
對(duì)于較舊的std libs),并且通過(guò)引用完成別名。
C ++ 11的移動(dòng)語(yǔ)義使得即使對(duì)于復(fù)雜對(duì)象,傳遞和返回值也更具吸引力。
C ++ 03的經(jīng)驗(yàn)法則:
通過(guò)const
引用傳遞參數(shù),除非
它們將在函數(shù)內(nèi)部進(jìn)行更改,并且此類更改應(yīng)反映在外部,在這種情況下,您將通過(guò)非
const
引用傳遞該函數(shù)應(yīng)該是可調(diào)用的,沒有任何參數(shù),在這種情況下,你通過(guò)指針傳遞,以便用戶可以傳遞
NULL
/0
/nullptr
; 應(yīng)用先前的規(guī)則來(lái)確定是否應(yīng)該通過(guò)指向const
參數(shù)的指針它們是內(nèi)置類型,可以通過(guò)復(fù)制傳遞
它們是在函數(shù)內(nèi)部將被改變并且這些變化應(yīng)不被外部的反射,在這種情況下,可以通過(guò)復(fù)制通過(guò)(一個(gè)替代方法是,根據(jù)前述規(guī)則,以通過(guò)和使函數(shù)的內(nèi)部副本)
(這里,“按值傳遞”被稱為“按副本傳遞”,因?yàn)榘粗祩鬟f總是在C ++中創(chuàng)建一個(gè)副本03)
還有更多,但這些初學(xué)者的規(guī)則會(huì)讓你走得更遠(yuǎn)。

TA貢獻(xiàn)1934條經(jīng)驗(yàn) 獲得超2個(gè)贊
C ++和Java中的調(diào)用約定存在一些差異。在C ++中,從技術(shù)上講,只有兩種約定:按值傳遞和按引用傳遞,一些文獻(xiàn)包括第三次傳遞指針約定(實(shí)際上是指針類型的值傳遞)。最重要的是,您可以將const-ness添加到參數(shù)的類型中,從而增強(qiáng)語(yǔ)義。
通過(guò)引用傳遞
通過(guò)引用傳遞意味著該函數(shù)將在概念上接收您的對(duì)象實(shí)例而不是它的副本。該引用在概念上是調(diào)用上下文中使用的對(duì)象的別名,并且不能為null。在函數(shù)內(nèi)執(zhí)行的所有操作都適用于函數(shù)外部的對(duì)象。此約定在Java或C中不可用。
按值傳遞(并按指針傳遞)
編譯器將在調(diào)用上下文中生成對(duì)象的副本,并在函數(shù)內(nèi)使用該副本。在函數(shù)內(nèi)執(zhí)行的所有操作都是對(duì)副本完成的,而不是外部元素。這是Java中基本類型的約定。
它的一個(gè)特殊版本是將指針(對(duì)象的地址)傳遞給函數(shù)。函數(shù)接收指針,并且應(yīng)用于指針本身的任何和所有操作都應(yīng)用于副本(指針),另一方面,應(yīng)用于解除引用指針的操作將應(yīng)用于該內(nèi)存位置的對(duì)象實(shí)例,因此該函數(shù)可能有副作用。使用指向?qū)ο蟮闹羔槀鬟f值的效果將允許內(nèi)部函數(shù)修改外部值,如使用pass-by-reference,并且還允許可選值(傳遞空指針)。
這是C函數(shù)需要修改外部變量時(shí)使用的約定,以及Java中使用引用類型的約定:引用被復(fù)制,但引用的對(duì)象是相同的:引用/指針的更改在外部不可見該函數(shù),但對(duì)指向內(nèi)存的更改是。
將const添加到等式中
在C ++中,您可以在定義不同級(jí)別的變量,指針和引用時(shí)為對(duì)象分配常量。您可以將變量聲明為常量,可以聲明對(duì)常量實(shí)例的引用,并且可以定義所有指向常量對(duì)象的指針,指向可變對(duì)象的常量指針和指向常量元素的常量指針。相反,在Java中,您只能定義一個(gè)級(jí)別的常量ness(final關(guān)鍵字):變量的類型(基本類型的實(shí)例,引用類型的引用),但是您不能定義對(duì)不可變?cè)氐囊茫ǔ穷惐旧硎遣豢勺兊模?/p>
這在C ++調(diào)用約定中廣泛使用。當(dāng)對(duì)象很小時(shí),您可以按值傳遞對(duì)象。編譯器將生成一個(gè)副本,但該副本不是一個(gè)昂貴的操作。對(duì)于任何其他類型,如果函數(shù)不會(huì)更改對(duì)象,則可以將引用傳遞給該類型的常量實(shí)例(通常稱為常量引用)。這不會(huì)復(fù)制對(duì)象,而是將其傳遞給函數(shù)。但同時(shí)編譯器將保證在函數(shù)內(nèi)部不更改對(duì)象。
經(jīng)驗(yàn)法則
這是一些要遵循的基本規(guī)則:
首選基本類型的傳值
對(duì)于其他類型的引用,首選引用傳遞
如果函數(shù)需要修改參數(shù),請(qǐng)使用pass-by-reference
如果參數(shù)是可選的,請(qǐng)使用pass-by-pointer(如果不應(yīng)修改可選值,則為常量)
這些規(guī)則還有其他小的偏差,第一個(gè)是處理對(duì)象的所有權(quán)。當(dāng)使用new動(dòng)態(tài)分配對(duì)象時(shí),必須使用delete(或其[]版本)對(duì)其進(jìn)行解除分配。負(fù)責(zé)銷毀對(duì)象的對(duì)象或函數(shù)被視為資源的所有者。當(dāng)在一段代碼中創(chuàng)建動(dòng)態(tài)分配的對(duì)象,但是所有權(quán)被轉(zhuǎn)移到另一個(gè)元素時(shí),通常使用pass-by-pointer語(yǔ)義,或者如果可能的話使用智能指針。
邊注
重要的是要堅(jiān)持C ++和Java引用之間差異的重要性。在C ++中,引用在概念上是對(duì)象的實(shí)例,而不是對(duì)象的訪問(wèn)者。最簡(jiǎn)單的例子是實(shí)現(xiàn)交換功能:
// C++class Type; // defined somewhere before, with the appropriate operationsvoid swap( Type & a, Type & b ) { Type tmp = a; a = b; b = tmp;}int main() { Type a, b; Type old_a = a, old_b = b; swap( a, b ); assert( a == old_b ); assert( b == old_a ); }
上面的交換函數(shù)通過(guò)使用引用來(lái)更改其參數(shù)。Java中最接近的代碼:
public class C { // ... public static void swap( C a, C b ) { C tmp = a; a = b; b = tmp; } public static void main( String args[] ) { C a = new C(); C b = new C(); C old_a = a; C old_b = b; swap( a, b ); // a and b remain unchanged a==old_a, and b==old_b }}
Java版本的代碼將在內(nèi)部修改引用的副本,但不會(huì)在外部修改實(shí)際的對(duì)象。Java引用是沒有指針?biāo)阈g(shù)的C指針,它們通過(guò)值傳遞給函數(shù)。

TA貢獻(xiàn)1815條經(jīng)驗(yàn) 獲得超13個(gè)贊
有幾種情況需要考慮。
參數(shù)修改(“out”和“in / out”參數(shù))
void modifies(T ¶m);// vsvoid modifies(T *param);
這種情況主要是關(guān)于樣式的:你想讓代碼看起來(lái)像call(obj)還是call(&obj)?但是,有兩點(diǎn)是重要的:下面是可選的情況,并且您希望在重載運(yùn)算符時(shí)使用引用。
......和可選的
void modifies(T *param=0); // default value optional, too// vsvoid modifies();void modifies(T ¶m);
參數(shù)未修改
void uses(T const ¶m);// vsvoid uses(T param);
這是一個(gè)有趣的案例。經(jīng)驗(yàn)法則是“便宜復(fù)制”類型是通過(guò)值傳遞的 - 這些通常是小類型(但并非總是) - 而其他類型則由const ref傳遞。但是,如果您需要在函數(shù)內(nèi)復(fù)制,則應(yīng)按值傳遞。(是的,這暴露了一些實(shí)現(xiàn)細(xì)節(jié).C'est le C ++。)
......和可選的
void uses(T const *param=0); // default value optional, too// vsvoid uses();void uses(T const ¶m); // or optional(T param)
所有情況之間的差異最小,因此請(qǐng)選擇最適合您生活的方式。
Const by value是一個(gè)實(shí)現(xiàn)細(xì)節(jié)
void f(T);void f(T const);
這些聲明實(shí)際上是完全相同的功能! 當(dāng)傳遞值時(shí),const純粹是一個(gè)實(shí)現(xiàn)細(xì)節(jié)。 試試看:
void f(int);void f(int const) { /* implements above function, not an overload */ }typedef void NC(int); // typedefing function typestypedef void C(int const);NC *nc = &f; // nc is a function pointerC *c = nc; // C and NC are identical types
- 4 回答
- 0 關(guān)注
- 820 瀏覽
添加回答
舉報(bào)