C C 函式中引數和返回值傳遞簡記

2021-08-26 09:50:24 字數 2258 閱讀 2134

原文:c/c++ 函式引數和返回值傳遞機制

簡單記錄一下 c++ 函式呼叫中,引數和返回值傳遞的方法和步驟

函式引數的傳遞是初始化語義:用呼叫者的實參去初始化函式的形參,如果引數是物件,需要呼叫該類的拷貝建構函式,如果沒有顯式定義的拷貝建構函式,則執行預設的按成員拷貝

函式返回值的傳遞內容稍多,示例**:

testclass get_test_obj() void user()

返回過程執行下列步驟:

1. get_test_obj() 中,用返回物件 ret_obj 初始化乙個型別為 testclass(返回型別)的 臨時物件 tmp_obj(假設名),這個臨時物件放置在呼叫者 user() 的棧內。gcc 4 和 vc 2005 使用返回值臨時物件的方式不同,見下面

bjarne 關於臨時物件銷毀的說法:臨時物件在維持它的那條語句之後被銷毀,除非臨時物件被約束到其它名字,此時由這個命名名字控制臨時物件的生存期。可以用物件初始化的語法(顯示或隱式的),或物件引用來約束這個臨時物件,兩者的效果是一樣的,因為期間只有乙個物件本體,就是臨時物件的本體,約束期間不產生任何初始化、賦值語義

2. get_test_obj() 中,由 ret_obj 的生存期,決定何時將其銷毀。如果 ret_obj 是區域性物件(形參 或 函式內定義非 static 變數),則在返回時銷毀

3. 如果 user() 中使用函式返回值進行 賦值操作 obj = get_test_obj(),則執行 obj.operator=(tmp_obj),沒有過載的 testclass::operator=(right) 和 ::operator=(testclass, right) 時,執行 testclass 的每個成員的 operator=()

4. 如果 user() 中使用函式返回值進行 初始化操作,包括以下幾種語法:

testclass obj = get_test_obj(); // 隱式初始化 testclass obj(get_test_obj()); // 顯式初始化 testclass& obj_ref = get_test_obj(); // 初始化為引用,tmp_obj 被約束到引用名

隱式和顯式初始化可能有 2 種實現:

(1). 直接將函式 get_test_obj() 返回的臨時物件 tmp_obj 約束到 obj,不呼叫 testclass 的任何建構函式(包括拷貝建構函式),在初始化語句執行後,不會銷毀 tmp_obj,而由 obj 控制 tmp_obj 的生存期

(2). 呼叫 testclass 的拷貝建構函式,以返回的 tmp_obj 為引數拷貝構造物件 obj。這種方式,在初始化語句執行後,tmp_obj 就沒有用了,將被銷毀

vc 2005 採用 (1) 方式實現

-o0 關閉編譯優化

無論是在 user() 內使用返回值賦值、初始化,還是不使用返回值,在 get_test_obj() 返回時,都 不建立額外的臨時物件 tmp_obj,而直接將 get_test_obj() 的區域性物件 testclass ret_obj(200) 作為臨時物件,即被調函式返回後,將其棧交給呼叫者控制,作為呼叫者的棧,這種返回物件的方法比 vc 2005 的效率高

下面是 gcc 4 中,呼叫者使用函式返回值的幾種情況:

1. 如果呼叫者沒有使用返回值,在被調函式返回時銷毀 return ret_obj 中的 ret_obj

2. 進行返回值賦值 或 初始化物件時,方式和 vc 2005 類似,只是不建立臨時物件 tmp_obj,而使用區域性物件 ret_obj

3. 當初始化返回值到引用名時,不能初始化到 非常量 的引用 testclass& obj_ref = get_test_obj(),會報編譯錯誤:

error: invalid initialization of non-const reference of type 『testclass&』 from a temporary of type 『testclass』

應該使用常量引用 const testclass& obj_ref = get_test_obj()

另乙個 gcc 4 有別於 vc 2005 的 const 保護行為:乙個 const 物件呼叫的方法必需是 const 方法,比如 const testclass obj 呼叫 obj.print_intval() 時,如果不是 void print_intval() const,會報編譯錯誤:

error: passing 『const testclass』 as 『this』 argument of 『void testclass::print_intval()』 discards qualifiers

C函式引數傳遞與返回值傳遞

1 引數傳遞 stdcall和 cdecl都是函式呼叫約定關鍵字,先給出這兩者的區別,然後舉例項分析 stdcall 引數由右向左壓入堆疊 堆疊由函式本身清理。cdecl 引數也是由右向左壓入堆疊 但堆疊由呼叫者清理。另外,這兩者在同一名字修飾約定下,編譯過後變數和函式的名字也不一樣,具體見另一博文...

引數傳遞以及返回值

在呼叫乙個方法時,我們經常傳入我們需要的引數,對於基本型別的傳入,在執行方法時直接用即可,這裡僅介紹幾種引用型別的引數傳遞 類名作為形式引數 如果乙個方法的形參要乙個類 型別,就傳入乙個該類的物件 根據 可知,建立物件時完成初始化,此時物件裡的的num時2,在呼叫方法時,傳入30,替代了原來的2,所...

函式引數和函式返回值

思考乙個問題,如下 現在需要定義乙個函式,這個函式能夠完成2個數的加法運算,並且把結果列印出來,該怎樣設計?下面的 可以嗎?有什麼缺陷嗎?def add2num a 11 b 22 c a b print c為了讓乙個函式更通用,即想讓它計算哪兩個數的和,就讓它計算哪兩個數的和,在定義函式的時候可以...