模板引數傳遞的區別 針對於函式模板的自動型別推導

2021-10-13 10:08:12 字數 3185 閱讀 2836

按值傳遞的後果是:導致函式模板的自動型別推導退化(decay),何為退化,下面就讓我仔細的說一下:

① 按值傳遞會導致傳入引數失去const和volatile屬性:

我們看到,函式形參的型別與我們傳入的實參型別不一致,去掉了const常量屬性。

volatile 關鍵字是一種型別修飾符,用它宣告的型別變數表示可以被某些編譯器未知的因素更改。比如:作業系統、硬體或者其它執行緒等。遇到這個關鍵字宣告的變數,編譯器對訪問該變數的**就不再進行優化,從而可以提供對特殊位址的穩定訪問。

宣告時語法:volatile int vint;

當要求使用 volatile 宣告的變數的值的時候,系統總是重新從它所在的記憶體讀取資料,即使它前面的指令剛剛從該處讀取過資料。例如:

volatile int i=10;  

int a = i;  

int b = i;

volatile 指出 i 是隨時可能發生變化的,每次使用它的時候必須從 i的位址中讀取,因而編譯器生成的彙編**會重新從i的位址讀取資料放在 b 中。而優化做法是,由於編譯器發現兩次從 i讀資料的**之間的**沒有對 i 進行過操作,它會自動把上次讀的資料放在 b 中。而不是重新從 i 裡面讀。這樣以來,如果 i是乙個暫存器變數或者表示乙個埠資料就容易出錯,所以說 volatile 可以保證對特殊位址的穩定訪問。

下面通過插入彙編**,測試有無 volatile 關鍵字,對程式最終**的影響:

#include void main()  

int b = i;  

printf("i = %d", b);  

}

然後,在 debug 版本模式執行程式,輸出結果如下:

i = 10  

i = 32

然後,在 release 版本模式執行程式,輸出結果如下:

i = 10  

i = 10

輸出的結果明顯表明,release 模式下,編譯器對**進行了優化,第二次沒有輸出正確的 i 值。下面,我們把 i 的宣告加上 volatile 關鍵字,看看有什麼變化:

#include void main()  

int b = i;  

printf("i = %d", b);  

}

分別在 debug 和 release 版本執行程式,輸出都是:

i = 10  

i = 32

這說明這個 volatile 關鍵字發揮了它的作用。其實不只是「內嵌彙編操縱棧」這種方式屬於編譯無法識別的變數改變,另外更多的可能是多執行緒併發訪問共享變數時,乙個執行緒改變了變數的值,怎樣讓改變後的值對其它執行緒 visible。一般說來,volatile用在如下的幾個地方:

1) 中斷服務程式中修改的供其它程式檢測的變數需要加volatile;

2) 多工環境下各任務間共享的標誌應該加volatile;

3) 儲存器對映的硬體暫存器通常也要加volatile說明,因為每次對它的讀寫都可能由不同意義。

② 按值傳遞會導致傳入引數失去引用屬性:

③ 按值傳遞會導致傳遞的陣列退化成指標:

我們看到,當使用顯式型別的時候,傳入的ch資料是陣列的首位址,我們可以在函式內部判斷出這個傳入引數是函式的首位址,但是當使用隱式型別轉換,即自動型別推導時,在函式內部這個指標就是乙個普通的指標。

#include using namespace std;  

#include #include template void showinf(t& obj)  

}  int main()  

這裡,我們按照引用傳遞乙個const int&的變數,因此此時的模板t&是const int&,即t為const int型別,我們要注意的是t是const int並非const int&。我們看到當使用t&進行隱式型別推到時,可以正確地推導出資料的型別。

#include using namespace std;  

#include #include template void showinf(t& obj)  

else  

}    

int main()  

當使用&進行資料型別推導時,可以保留陣列指標的特性,不至於退化為普通指標。

注意:typeid.name()輸出的是const char*資料型別的常量,比如int, const int*等, 但是遺憾的是這種方式輸出不了const int&:

我們從結果看到,這個變數的型別確實是const int&,但是這裡卻沒顯示。

函式模板與類模板的區別

函式模板與類模板有什麼區別?答 函式模板的例項化是由編譯程式在處理函式呼叫時自動完成的,而類模板的例項化必須由程式設計師在程式中顯式地指定。即函式模板允許隱式呼叫和顯式呼叫而類模板只能顯示呼叫 這期間有涉及到函式模板與模板函式,類模板與模板類的概念 類似於類與類物件的區別 請看下面例子 注意 模板類...

函式模板與類模板的區別

函式模板與類模板有什麼區別?答 函式模板的例項化是由編譯程式在處理函式呼叫時自動完成的,而類模板的例項化必須由程式設計師在程式中顯式地指定。即函式模板允許隱式呼叫和顯式呼叫而類模板只能顯示呼叫 這期間有涉及到函式模板與模板函式,類模板與模板類的概念 類似於類與類物件的區 別 請看下面例子 注意 模板...

C 的可變引數模板函式

可變引數模板函式寫法 模板引數裡寫typename.args,表明args是乙個可變引數。之後再函式引數裡args後面也要加.以表示該引數為可變引數。函式引數中對於args的修飾,會擴充套件到所有該args的引數,比如下面 可變引數模板函式使用方法1 遞迴呼叫,每次將可變引數規模變小直到為0 tem...