[C/C++]函式如何返回struct或class物件
本文寫於我對C++尚不是很瞭解的時期,所以文中存在很多漏洞。為了避免浪費你的時間,請繞道!
所有的C、C++教科書都警告我們:不要通過函式來返回struct或 class物件,否則會造成記憶體複製以及複製建構函式的呼叫,降低效能。相信這句話已經成為了一個常識,大家都能牢記於心。然而,有時候我們不得不違反這個警告,例如,通過函式獲取一個std::string物件(以個人的經驗而言,這種情況是很常見的,我經常要通過函式建立一個新的物件)。不知道從什麼時候起,當我面對這種情況的時候會通過引用來獲取這個物件,像這樣:
1 2 |
std::string
GetString(); std::string&
str = GetString();
|
這樣子給我的感覺會好一點,讓我覺得物件的複製次數少了。然而這只是一種憑空猜想,沒有經過任何證實。為了弄清楚這樣做究竟會不會帶來效能的提升,我決定研究一下函式是如何返回struct或class物件的。最好的研究途徑當然是反彙編編譯器生成的機器碼了。
我的實驗環境是Visual Studio 2010,所有程式碼都是Debug版本的,因為這樣生成的機器碼是最原始的,沒有經過任何優化,可以顯示出真實的情況。而Release版本的機器碼經過了優化,已經是“面目全非”,所以本文不考慮該版本。另外,對於struct來說,Visual Studio 2010 的C編譯器和C++編譯器生成的程式碼是一樣的,所以本文所有程式碼都通過C++編譯器來編譯。注意,使用不同的編譯器可能會有不同的結果!
如何返回struct物件
首先來看一下函式如何返回struct物件。分兩種情況:第一種情況是struct的大小是1位元組、2位元組或4個位元組,可以放到al、ax或eax暫存器中;第二種情況是struct的大小不是上面提到的三個值,不能放到暫存器中(包括3個位元組的)。要注意,這裡所說的“大小”是指在記憶體中經過對齊後的大小,而不是定義的大小。如果沒有特別說明,下文提到的大小也是指經過對齊後的大小。
第一種情況:struct可以放到暫存器中
下面是第一種情況的典型例子,struct的大小是4個位元組:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
struct S
{
int Value;
};
S
GetS( int value)
{
S
s;
s.Value
= value;
return s;
}
int wmain()
{
S
s = GetS(10);
}
|
下面是GetS函式的部分彙編程式碼:
1 2 3 4 5 6 |
;s.Value
= value;
mov
eax,dword ptr [value]
mov
dword ptr [s],eax
;return
s;
mov
eax,dword ptr [s]
|
可以看到,s是直接通過eax來返回的,因為它的大小恰好可以放進eax暫存器中。
下面是S s = GetS(10);的彙編程式碼:
1 2 3 4 5 6 |
push
0Ah ;引數10入棧
call
GetS (8D1019h) ;呼叫GetS函式
add
esp,4 ;釋放參數空間
mov
dword ptr [ebp-0D4h],eax ;將返回值儲存到臨時空間
mov
eax,dword ptr [ebp-0D4h] ;從臨時空間裡取出返回值
相關推薦[C/C++]函式如何返回struct或class物件本文寫於我對C++尚不是很瞭解的時期,所以文中存在很多漏洞。為了避免浪費你的時間,請繞道! 所有的C、C++教科書都警告我們:不要通過函式來返回struct或 class物件,否則會造成記憶體複製以及複製建構函式的呼叫,降低效能。相信這句話已經成為了一個常識 c++中memset給一個struct或class初始化,賦0memset函式的用法 將緩衝區設定為指定的字元。 下面是網上常見的說法,也就是memset函式的用法 函式功能是:將s所指向的某一塊記憶體中的前n個位元組的內容全部設定為ch指定的ASCII值, C語言 函式返回一位陣列,二維陣列方法一: 萬能的結構體:構造陣列的結構體,將函式型別定義為此型別 但是考試的時候應該不太方便寫結構體,寫不下也會很麻煩,故介紹方法二 方法二: 指標傳遞: 1、返回一維陣列 例子:將陣列每一位加一: #include<stdio.h> #define N 10 int C從函式返回陣列C 語言不允許返回一個完整的陣列作為函式的引數。但是,可以通過指定不帶索引的陣列名來返回一個指向陣列的指標。如果您想要從函式返回一個一維陣列,必須宣告一個返回指標的函式,如下: int * myFunction() { } 另外,C 不支援在函式外返回區域性變數的地址,除非定義區域性 C++中函式返回陣列指標的幾種方法總結因為陣列不能被拷貝,所以函式不能返回陣列。不過,函式可以返回陣列的指標或引用。返回陣列指標的方法有以下幾種: 1、方法一:使用類型別名。如下 typedef int arrt[10];//arrT是一個類型別名,它表示的型別是含有10個整數的陣列 C語言函式返回值的實現方法和誤區例項:你們認為這三個函式能正常返回嗎? int func1(int a , int b) { int c = 0; c = a + b; return c; } char * func2() { char *strTmp = "abs"; return str C++ 從函式返回陣列C++ 不允許返回一個完整的陣列作為函式的引數。但是,您可以通過指定不帶索引的陣列名來返回一個指向陣列的指標。 如果想要從函式返回一個一維陣列,就必須宣告一個返回指標的函式,如下: int * myFunction() { . . . } 另外,C++ 不支援在函式外返回區域性變數的地址 C++虛擬函式、虛繼承、物件記憶體模型虛擬函式的工作原理 虛擬函式的實現要求物件攜帶額外的資訊,這些資訊用於在執行時確定該物件應該呼叫哪一個虛擬函式。典型情況下,這一資訊具有一種被稱為 vptr(virtual table pointer,虛擬函式表指標)的指標的形式。vptr 指向一個被稱為 vtb C++面試題一---Struct和Class的區別C++中的struct對C中的struct進行了擴充,它已經不再只是一個包含不同資料型別的資料結構了,它已經獲取了太多的功能。 struct能包含成員函式嗎? 能! struct能繼承嗎? 能!! struct能實現多型嗎? 能!!! 既然這些它都能實現 誤人子弟篇之C語言函式返回值與引數傳遞寫在開頭以免看到結尾你,此篇部落格純屬瞎扯,看看就可以了,不要當真哦! 如果搞過彙編,寫過子程式,那麼你就不用看了,因為看到最後你會發現,在彙編中你有很多方法去返回值,傳遞引數,而在高階語言中,編譯器只是選擇了其中的一種而已,而這篇部落格也寫的毫無邏輯,簡直喪盡天良,草菅人 程式設計基礎-------C語言函式返回二維陣列的做法在C語言中,有時我們需要函式的返回值為一個二維陣列。這樣外部函式接收到這個返回值之後,可以把接收到的二維陣列當成矩陣操作(外部函式不可用普通的一級指標接收返回值,這樣的話,外部函式將不知道它具有二維性)。方法如下: 法1.沒有使用typedef型別定義 #inc 如何讓C語言函式返回一個二維陣列為了讓C語言函式返回一個二維陣列,有些人這樣定義函式: int **foo(int rows, int columns) 然後在函式中費勁心機拼出來一個這樣的malloc語句: int (*result)[columns] = (int (*)[c C++ 從函式返回指標(函式外返回區域性靜態變數的地址)C++ 不支援在函式外返回區域性變數的地址,除非定義區域性變數為 static 變數。 錯誤程式碼: int main(){ int *p; p=funcGetPointer() C++中函式返回值的引用型別與非引用型別的區別返回值為引用型別的函式某些情況下可作為表示式的左值,而非引用的則一般不可以。 函式返回值若為引用型別,當返回的是函式的引用形參時,則是對函式外的變數的引用,函式可以作為表示式的左值(被賦予新值)。 而當函式返回的是非引用型別時,返回的值是函式內隱式生成的 java-靜態同步函式的鎖是Class物件/* 如果同步函式被靜態修飾後,使用的鎖是什麼呢? * 通過驗證,發現不在是this。因為靜態方法中也不可以定義this * 靜態進記憶體是,記憶體中沒有本類物件,但是一定有該類對應的位元組碼檔案物件。 * 類名.class 該物件的型別是Class * 靜態的同步 (多執行緒-靜態同步函式的鎖是Class物件)/* 如果同步函式被靜態修飾後,使用的鎖是什麼呢? 通過驗證,發現不在是this。因為靜態方法中也不可以定義this。 靜態進記憶體是,記憶體中沒有本類物件,但是一定有該類對應的位元組碼檔案物件。 類名.class 該物件的型別是Class 靜態的同 c / C++ 中的struct 和memcpy函式 class 物件成員變數記憶體是否連續對於c語言中 使用memcpy 函式來拷貝一個struct結構並沒有什麼不妥 但是在c++ 中出現了物件的概念,所以 對於struct物件總會有些不同吧,相對於c的struct 如果完全一樣的話就沒有必要設計class了。 當然在c++ 中class和struct還是 【C++】函式和結構--struct經典程式--傳遞結構和返回結構的程式碼示例(1)結構和陣列的差異(基本概念) 為結構編寫函式比為陣列編寫函式要簡單得多。 結構是一個實體,被 看做一個整體,可以將一個結構賦給另一個結構。 函式可以返回結構。陣列名就是陣列第一個元素的地址,而結構名只是結構的名稱,要想獲得結構的地址,必須使用地址運算子& 然而,按 C++基礎知識(八)---函式返回值(返回值,返回指標,返回物件,返回引用)---引用---複製建構函式(拷貝建構函式)一、函式返回值 1.返回值: int test () { int a=1; return a; } 返回值時最簡單的方式,它的操作主要在棧上,變數a在函式結束後會刪除,為了返回a的值,系統會在內部建立一個臨時變數儲存a的值,以返回給呼叫該函式的表示式,呼叫結束後變數便 C++函式返回臨時指標物件的隱患現在編譯器一般對臨時物件有優化,可以直接返回並使用,之前為了方便,若是介面指標,直接返回臨時物件,因為使用雙指標或引用總是要多操作幾步,今天遇到了一個很大的隱患。 //被調函式 CATIPLMNavReference_var GetRefFromOcc(const CAT |