1. 引用
?
int main()
{const int a=10;int& aa=a;aa++;cout<<aa<<endl;
}
在這個代碼里面aa是a的別名,aa++了,也就是a++;所以這里的輸出是11;
舉個例子,現在有一個人叫小明,我們給他取一個別名叫明明,明明去吃飯了,那是不是小明也去吃飯了,引用就是這個意思。
1.1 常引用
?int main()
{const int a=10;int& aa=a;aa++;cout<<aa<<endl;
}
在這個代碼里面,如果a是const int類型的,那就不可以對aa進行++的操作(會報錯)。
舉個例子,小明不可以吃飯,那也就是說明明不可以吃飯。
1.2 傳值返回與傳引用返回
int Fanc(int a)
{a++;return a;
}int main()
{int b=1;b=Fanc(b);cout<<b<<endl;return 0;
}
在這段代碼里面,最終的結果是2。但是他在return a的時候產生了一份臨時拷貝,然后把這個臨時拷貝賦值給了b。我們前面說的消耗就是在這里。
PS:之所以要拷貝的原因涉及到函數棧幀的創建與銷毀,簡單來說就是a出了這個Fanc就會自動銷毀,所以編譯器要通過產生臨時拷貝的方式來進行賦值。
傳引用返回:
?int& Fanc(int a)
{a++;return a;
}int main()
{int b=1;b=Fanc(b);cout<<b<<endl;return 0;
}
在這段代碼里面,a其實是有危險的,因為是&,所以在這里并沒用產生a的臨時拷貝,也就是說在這里實際上造成了野指針現象。
修改的辦法有兩種。
一種是加一個全局變量
int c;// 全局變量int& Fanc(int a) {c = a + 1; return c;
}int main() {int b = 1;b = Fanc(b);cout << b << endl; return 0;
}
傳入的是全局變量(或者靜態變量也可以),所以在這里并不會被銷毀。
還有一種是通過引用傳遞參數
int& Fanc(int& a) {a++; // 直接修改傳入的參數return a; // 返回傳入參數的引用
}int main() {int b = 1;Fanc(b); cout << b << endl; return 0;
}
通過引用傳遞參數,直接修改傳入的參數并返回其引用 1.3?傳值、傳引用
首先,傳值和傳引用與傳值返回與傳引用返回不是同一個東西。
傳值:
??int Fanc(int a)
{a++;return a;
}int main()
{int b=1;b=Fanc(b);cout<<b<<endl;return 0;
}
這個就是我們在一開始的學習中使用函數的方式。消耗也比較大。
傳引用:
?
?int Fanc(int& a)
{a++;return a;
}int main()
{int b=1;Fanc(b);//沒有了b=...cout<<b<<endl;return 0;
}?
直接修改傳入的參數,而不需要返回值。同時代價也小。
1.4?引用和指針的區別
在C++中,引用和指針都是用來間接訪問變量的機制,但它們之間有一些重要的區別:
1. 引用是變量的別名,而指針是一個獨立的實體。引用在聲明時必須初始化,并且一旦引用和原變量綁定后,就無法再綁定到其他變量(這一點很重要);而指針可以在聲明后指向不同的變量。
2. 引用不需要使用解引用操作符(*)來訪問其綁定的變量,而指針需要使用解引用操作符(*)來訪問其指向的變量。
3. 引用不能指向空值(null),而指針可以指向空值。
4. 指針可以進行算術運算,而引用不支持。
總的來說,引用更直觀和安全,因為它不需要對空值進行處理,而指針更靈活,因為它可以指向不同的對象和進行算術運算。在實際使用中,應根據具體情況選擇合適的機制。
2. 內聯函數
inline int add(int a, int b)
{return a + b;
}int main()
{int result = add(3, 4); // 編譯器可能會將 add 函數直接插入此處cout << "Result: " << result << endl;return 0;
}
內聯函數的本質就是替換,通過把main函數里面的add直接轉換成a+b,通過這樣的方式來提升效率。
2.1?內聯函數特性
3. auto關鍵字
auto我從剛剛學到他的時候認為沒什么用,但是當我學到后面的時候,我才發現他是那么的好用,因為到后面很多時候類型是一層套一層,就是說會特別的長,這個時候auto的作用就體現出來了。
他的本質就是讓編譯器自動推導類型。換種說法就是把我們的這部分工作交給了編譯器。
3.1 auto使用時候的注意事項
int main()
{auto x = 10,y=3;return 0
}
上面這種就是合法的,因為auto在同一行只會進行一次推導,如果說y=3.3,那么編譯器就會報錯。
3.2 auto不能推導的類型
auto不可以作為函數的參數類型,比如說:
auto fanc(auto a)
{.......
}
這種是不合法的(其實沒有什么別的原因,就是設計者在設計的時候沒有允許這種用法,我們在后面會學到一種template<class T>的東西,他可以實現我們上面想要達到的目的)。
同時,auto也不可以作為數組的類型,簡單來說就是:
int main()
{auto arr[]={1,2,3,4,5,6}return 0;
}
這種也是不可以的(原因如上)。
4. 范圍for
void TestFor()
{int arr[] = { 1, 2, 3, 4, 5 };for(auto& a : arr)a *= 2;
}
這就是范圍for的用法,通過這樣的方式就可以使arr里面的數都*上2。
PS:加上引用就可以改變arr,如果說是想要改變范圍for里面的數組,那最好就是在auto后面加一個&。
4.1 范圍for的原理
范圍for的底層就是迭代器(iterator),他在編譯器編譯的時候就會修改為迭代器。
所以說我們在里面想要遍歷或者修改的東西必須有begin和end的方法,begin和end就是for循環迭代的范圍。