對於使用者自定義的型別來說,傳引用一般要比傳值高效。傳引用不需要經過物件過程,在《effective c++》中作者舉了個例子:
class base
class derive : public base
此刻我們擁有乙個派生類物件derive 。對derive傳值的結果是共需要進行六次的建構函式的呼叫:物件本身的建構函式,物件內部資料成員string的構造,物件基類部分的建構函式,物件基類資料成員string的構造。同樣的,待物件生命結束後,還要經歷6次析構函式的呼叫。而傳引用則不用進過如此多的構造與析構,甚至一次都不用。
對內建型別來說,傳值的效率往往要高於傳引用。內建型別包括了int,float ,double,指標型別等等。看下面的程式:
void f(int i)
void g(int & i)
int main()
當通過傳值呼叫函式f()時,其彙編**為:
當通過傳引用呼叫函式g()時,其彙編**為:
可以看到,傳引用比傳值多了一次定址操作,這是因為引用的實現往往基於指標,因此傳引用通常意味著真正傳遞的是指標。
總結:對內建型別來說,通常傳值更高效。
對用於自定義型別來所,傳值要經歷構造與析構過程,一般比較耗時。
傳值有時會引起物件的切割問題。就上面所示的兩個類,當我們定義如下函式並進行傳值呼叫時:
void func(base b)
int main()
編譯器將呼叫base類的複製建構函式來初始化b,初始化資料**於a,但構造結果是個base類物件:也就意味著a的特有部分的資料被切割掉了。在函式func中,b的行為是乙個base的行為而不是derive的行為。
通過傳引用,能夠避免切割的問題:
void func(base & b)
int main()
此時在函式func內,物件b實際型別為derive,通俗地將,b就是a。若希望在func中使用到實參的特性,傳引用能夠保證這一點。
如果你開啟stl中的原始碼,你會發現容器的iterator都是通過傳值形式傳參。在《effective c++》中指出,對於內建型別、stl 迭代器和 stl 仿函式,pass-by-value 也是可以的,一般沒有效能損失。在 x86-64 上,對於只有乙個 指標成員且沒有自定義複製建構函式的類,傳值是可以通過暫存器進行的,就像傳遞普通 int 和指標那樣。如上所示,傳值是可以比傳引用快的沒有,因為它少了一次解引用的操作。
(完)
關於傳值與傳引用的討論
對於使用者自定義的型別來說,傳引用一般要比傳值高效。傳引用不需要經過物件過程,在 effective c 中作者舉了個例子 class base class derive public base 此刻我們擁有乙個派生類物件derive 對derive傳值的結果是共需要進行六次的建構函式的呼叫 物件本...
傳值與傳引用
python的函式傳值和傳引用,和c c 語言是一樣的。在開始之前,我們有必要分清一下python的一些基礎概念。首先要說的是 變數 與 物件 在python中,型別屬於物件,變數是沒有型別的,這正是python的語言特性,也是吸引著很多pythoner的一點。所有的變數都可以理解是記憶體中乙個物件...
傳值 傳值引用
首先對傳值和傳引用要有個基本的概念 傳值 傳遞的是值的副本。方法中對副本的修改,不會影響到呼叫方。傳引用 傳遞的是引用的副本,共用乙個記憶體,會影響到呼叫方。此時,形參和實參指向同乙個記憶體位址。對引用副本本身 物件位址 的修改,如設定為null,重新指向其他物件,不會影響到呼叫方。直接上 更好的理...