差分
回答
當你傳遞一個大的結構體/類時,區別更加突出。
struct MyData {
int a,b,c,d,e,f,g,h;
long array[1234];
};
void DoWork(MyData md);
void DoWork(const MyData& md);
當您使用'正常'參數時,您通過值傳遞參數,因此創建您傳遞的參數的副本。如果使用const引用,則通過引用傳遞它,並且不會複製原始數據。
在這兩種情況下,原始數據都不能從函數內部修改。
編輯:
在某些情況下,如在他的answer指出的Charles Bailey原始數據也許能得到改變。
第一種方法通過n
由值,即n
副本被髮送給該函數。第二個通過n
通過引用傳遞,這基本上意味着一個指向函數被調用的指針n
被髮送到該函數。
對於像int
這樣的整數類型,作爲常量引用傳遞沒有多大意義,因爲引用的大小通常與引用(指針)的大小相同。在製作副本昂貴的情況下,通常最好通過const引用傳遞。
大小不是唯一的問題。通過const引用傳遞允許在函數內部看見原始對象的變化。按值傳遞將函數體與這些更改隔離開來。 – 2010-04-13 05:33:10
@Charles當然,這在某些情況下確實可能是有益的(並且在某些情況下是有害的))。 – 2010-04-13 05:37:11
當通過值與參考引用** int **等類型傳遞類型時,您可以觀察到多線程環境中的不同行爲。 – 2010-04-13 05:55:37
隨着
void DoWork(int n);
n
是實際參數值的副本,它是合法的,在函數內改變n
值。隨着
void DoWork(const int &n);
n
是實際參數的引用,這是不合法的改變它的值。
既然你們沒有提到任何關於const關鍵字...
的常量關鍵字修改類型聲明或函數參數的類型,防止改變值的類型。 (來源:MS)
換句話說:通過引用傳遞一個參數將它暴露給被調用者修改。使用const關鍵字可防止修改。
重要的區別是,當傳遞const
引用時,不會創建新對象。在函數體中,參數實際上是傳入對象的別名。
因爲引用是const
引用,所以函數體不能直接更改該對象的值。這具有類似於傳遞值的特性,其中函數體也不能更改傳入的對象的值,在這種情況下,因爲參數是副本。
存在重大差異。如果該參數是const
引用,但傳遞它的對象實際上不是const
,那麼可以在函數調用本身期間更改該對象的值。
E.g.
int a;
void DoWork(const int &n)
{
a = n * 2; // If n was a reference to a, n will have been doubled
f(); // Might change the value of whatever n refers to
}
int main()
{
DoWork(a);
}
而且如果傳入的對象本來就不是const
則函數可以(即使是不明智的話)改變其與投值。
例如
void DoWork(const int &n)
{
const_cast<int&>(n) = 22;
}
如果傳入的對象實際上是const
,則會導致未定義的行爲。
當參數由const引用傳遞時,額外的成本包括解引用,更糟糕的對象局部性,編譯優化的機會更少。
當參數按值傳遞並且額外成本是需要創建參數副本的時候。通常這隻在對象類型很大時才需要考慮。
首先,沒有cv限定參考的概念。所以術語'const引用'是不正確的,通常用來描述'引用const'。開始談論什麼是最好的。
$ 8.3.2/1-「CV-合格引用不良時形成 cv修飾符通過使用一個typedef(7.1.3)或模板類型參數的 的引入除(14.3 ),在這種情況下,cv限定符 被忽略。「
這裏有
$ 13.1差異 - 「只有在最外層 水平的參數類型定義的常量和揮發性類型說明符以這種方式忽略; const和volatile類型說明符特別是對於任何類型的T, 「指向T的指針」,「指向const T的指針」以及「指向volatile的指針」的指針都是重要的,可用於區分 重載的函數聲明。 T「是 co nsidered不同參數類型,因爲是「參照T,」 「參考爲const T,」和「參照揮發性T.」
void f(int &n){
cout << 1;
n++;
}
void f(int const &n){
cout << 2;
//n++; // Error!, Non modifiable lvalue
}
int main(){
int x = 2;
f(x); // Calls overload 1, after the call x is 3
f(2); // Calls overload 2
f(2.2); // Calls overload 2, a temporary of double is created $8.5/3
}
有三種方法可以在功能
值傳遞通過值
void f(int n){ n=n+10; } int main(){ int x = 3; f(x); cout << x<<endl; }
輸出:3.缺點:當參數
x
通過f
函數,然後編譯器在x的內存中創建一個副本。所以浪費了記憶。通過引用傳遞
void f(int &n){ n=n+10; } int main(){ int x = 3; f(x); cout << x<<endl; }
輸出:13.消除值劣勢通,但如果程序員不希望更改值,然後使用恆定的參考
恆參考
void f(const int &n){ n=n+10; // Error: assignment of read-only reference ‘n’ } int main(){ int x = 3; f(x); cout << x<<endl; }
輸出:在
n=n+10
處拋出錯誤,因爲當我們傳遞const引用參數參數時n它是隻讀參數,不能更改n的值。
你的意思是在f()被調用之後在main()中有print語句嗎?因爲在f()裏面的print語句,我認爲第一個例子的輸出是錯誤的:它應該是13,不是? – Seb 2017-04-20 18:21:00
IIRC,const引用支持多態,但「正常參數」不支持,糾正我,如果我錯了 – Woofas 2017-08-30 05:28:46