C 為什麼要用傳引用常量替換傳值

2021-10-06 12:04:21 字數 1656 閱讀 2856

假設現在有乙個person類作為基類,還有乙個student類繼承自person,如下:

class person ;

class student : public person ;

現在我們有乙個函式,叫validatestudent,需要傳入乙個student物件,並返回它是否有效。

bool validatestudent(student s);

student plato;

bool platoisok = validatestudent(plato);

那麼在這個函式呼叫的過程中,會發生什麼事情呢?首先,student的拷貝建構函式會被呼叫,以plato為藍本將s進行初始化。同樣,函式執行結束後,這個建立的s會被銷毀。因此,這次引數傳遞的成本是"一次student拷貝建構函式的呼叫,加上一次student析構函式的呼叫"。然而,這只是其中的一部分,student物件內還有兩個string物件,所以,每次構造student物件也就構造了這兩個string物件。此外student物件繼承自person物件,每次構造student物件也必須構造出乙個person物件。乙個person物件又有兩個string物件在裡面。這麼看的話,通過傳值的方式傳遞乙個student物件,總的成本是"六次建構函式和六次析構函式"(包含了string物件的構造和析構)。

如果是通過傳遞引用常量的方式,則函式宣告應該這樣寫:

bool validatestudent(const student& s);
這種傳遞方式的效率要高得多,因為在這個過程中,沒有任何建構函式和析構函式的呼叫,因為沒有任何新的物件建立。這裡的const是必須的,因為呼叫者會憂慮validate會不會改變他們傳入的那個student,這麼做可以有效地保護傳入的物件。

先來看看下面這個window類:

class window ;

class windowwithscrollbars : public window

所有window物件都帶有乙個名稱,你可以通過name函式取得它。所有視窗都可以顯示,你可以通過display函式完成它。display是乙個virtual函式,這意味著簡易樸素的base class window物件的顯示方式和華麗高貴的windowwithscrollbars物件的顯示方式不同。

現在假設你希望寫個函式列印視窗名稱,然後顯示該視窗。下面是錯誤示範:

void printnameanddisplay(window w) 

windowwithscrollbars wwsb;

printnameanddisplay(wwsb);

引數w會構造乙個window物件, 它是pass by value的。這就會導致wwsb裡面包含的所有windowwithscrollbars的內容都會被切除。對於printnameanddisplay函式來說,不論傳過來的是什麼物件,引數w就是乙個window物件,其內部也會呼叫window::display。

解決切割(slicing)問題的辦法,就是以reference-to-const的方式傳遞w。則修改後的printnameanddisplay如下:

void printnameanddisplay(const window& w)

拷貝建構函式為什麼要用引用傳參?

拷貝建構函式是類的六個預設成員函式之一,他是建構函式的乙個過載形式,其引數只有乙個且必須要引用傳遞,那我們不禁想問值傳遞可以嘛?下面是乙個拷貝建構函式的 讓我們來分析下 date const date d intmain 當用已存在的物件建立新物件時候,編譯器會自動呼叫拷貝建構函式完成新物件的初始化...

C 傳值 傳址 傳指標 傳引用

相關概念 c 三種傳遞引數方式 傳引數的值 稱值傳遞,簡稱傳值 傳引數的位址 稱位址傳遞,簡稱為傳址 和引用傳遞 稱為傳引用 相應的函式傳值呼叫,傳址呼叫和傳引用呼叫 形參 實參 函式定義時參數列中的引數稱為形式引數,簡稱形參 函式呼叫時參數列中的引數稱為實際引數,簡稱實參。實參和形參之間的資料傳遞...

c 傳值,傳引用,傳指標比較

相關概念 c 三種傳遞引數方式 傳引數的值 稱值傳遞,簡稱傳值 傳引數的位址 稱位址傳遞,簡稱為傳址 和引用傳遞 稱為傳引用 相應的函式傳值呼叫,傳址呼叫和傳引用呼叫 形參 實參 函式定義時參數列中的引數稱為形式引數,簡稱形參 函式呼叫時參數列中的引數稱為實際引數,簡稱實參。實參和形參之間的資料傳遞...