# C++和C的差異 --- ### NameSpace(命名空間) 是一個識別碼的可見範圍。 >(維基舉例)就像一間公司中,某個員工Kitty的識別碼是217,而在另一間公司中也有一個人(可能是Teresa)的識別碼是217。但是因為他們是不同公司,即使識別碼相同,所代表的意思也不同,並不會導致薪水發錯或是叫錯人的問題。 如以下的code,這裡的`cout`和`cin`的namespace是屬於`standard library`,為了不要造成命名重複的誤會,所以原本的打法應該是 ```cpp= #include <iostream> int main(){ int a; std::cin >> a;//standard library中的cin std::cout << "Hello World!!\n";//standard library中的cout } ``` 而省略的寫法,就是在一開始就在一開始就指定namespace,之後用到此命名空間的東西,就不用再寫出來 ```cpp= #include <iostream> using namespace std; int main(){ int a; cin >> a; cout << "Hello World!!\n"; } ``` --- ### String >在使用之前,要記得`#include<string>` 和C不同的是,在C++中可以直接用`+`來連接字串 ```cpp= #include <iostream> #include <string> using namespace std; int main(){ string name = "Teresa", str; str = "Hello, " + name + "!\n";//use string like int in C cout << str; } ``` ```cpp= //OUTPUT Hello, Teresa! ``` --- ### Auto Type Inference C++中,如果在變數前面標示型別的地方標示 `Auto`,則程式會自行判斷這個變數中的值的型別 >結合vector的例子一起示範 --- ### Vector >記得`#include<vector>` `vector<int>` 的意思就是一個vector裡面每一個元素都是`int`,同理, `vector<string>`就是一個vector 裡面每一個元素都是string。另外,變數後不需要加等號(可加可不加) 下面例子,vector加上Auto Type Inference,示範C++的range-based for loop: ```cpp= #include<iostream> #include<vector> using namespace std; int main(){ vector<int> v {1, 2, 3, 4, 5};//v = {} is optional //to take out the int from the vector v //same as int i; i < len; ++i in C //auto means it can detemine the type for(auto i : v){ cout << i << ","; } cout << "\n"; } ``` Range-based for loop簡單來說就是不需要像C一樣多設一個index還要設定index範圍去跑整個vector,此種寫法會自動一序取出陣列的值,也不會有超過index範圍的問題。 >但這個功能有些用法還沒搞懂,先放著 --- ### Call by Reference 先說說C++中新的變數類型,Reference。 在C當中 `int`變數就是一個整數變數,`int*`就是一個整數的指標變數,`int &`就是一個某個整數變數的別名。 ```cpp= #include<iostream> using namespace std; int main(){ int a = 7; int *b = &a; int &c = a; cout << "a = " << a << endl; cout << "b = " << *b << endl; cout << "c = " << c << endl; *b = 8; cout << "After changing b,\n"; cout << "a = " << a << endl; cout << "b = " << *b << endl; cout << "c = " << c << endl; c = 17; cout << "After changing c,\n"; cout << "a = " << a << endl; cout << "b = " << *b << endl; cout << "c = " << c << endl; } ``` 當同樣都要改變a的值時,b需要先derefence,而c不需要。 c的任何存取,都會影響到a物件的操作。說白了,c就相當於a。 ```cpp= //OUTPUT a = 7 b = 7 c = 7 After changing b, a = 8 b = 8 c = 8 After changing c, a = 17 b = 17 c = 17 ``` 如果我們寫一個swap的function來比較指標變數和參考的差別,應該會比較清楚: ```cpp= #include<iostream> using namespace std; void swap_by_reference(int & i, int & j){ int tmp = i; i = j; j = tmp; } void swap_by_pointer(int *i, int*j){ int tmp = *i; *i = *j; *j = tmp; } int main(){ auto x = 5; auto y = 7; swap_by_pointer(&x, &y); cout << x << ", " << y << endl; swap_by_reference(x, y); cout << x << ", " << y << endl; } ``` ```cpp= //OUTPUT 7, 5 5, 7 ``` 一樣都能做到swap,但是當使用指標的時候,function裡面就需要dereference,但是當function中使用reference,就可以直接更改到`main`當中`x`和`y`的值。 當function的回傳值為reference時,不可以回傳function中的局部變數。(這個意思就是回傳的reference是function中變數的reference,但是當function結束後,function中的局部變數都不能再被使用,所以傳回來的東西就會是沒有意義的) ```cpp= #include<iostream> using namespace std; //a function which returns a reference int &max(int &i, int & j){ return (i > j) ? i : j; } int main(){ int x = 5; int y = 9; max(x, y) = 1; cout << x << ", " << y << endl; } ``` 以這個function為例,當跑完`max`之後會回傳`y`的reference(因為`y`比較大)到`main`裡面。然後在`main`裡面我們又去更動這個reference的值。 所以最後`cout`的`y`經歷了多出一個reference,又因為reference更動值而`y`的值從9變成1。 ```cpp= //OUTPUT 5, 1 ``` --- ### Lambda Function ```cpp= #include<iostream> #include<iomanip>//setw() #include<algorithm>//for_each() #include<vector>//push_back() using namespace std; int main(){ vector<int> v; for (int i = 1; i < 10;++i) v.push_back(i * 5); for(auto i:v) cout << setw(5) << i; cout << endl; for_each(v.begin(), v.end(),[](int n){ if (n % 2 == 0){ cout << n << " is even " << endl; } }); for(const auto y : v)cout << setw(5) << setfill('#') << y; cout << endl; for(auto & y : v) y = y + 1; for(const auto & y : v)cout << setw(5) << setfill('#') << y; cout << endl; } //question: what is the difference between auto y and const auto & y? ``` 寫到這裡有個疑問,`const auto & y`和`auto y`的差別在哪裡? 找到一個不錯的[參考資料](https://zhuanlan.zhihu.com/p/25148592),但我看不懂哈哈哈 把`class`上完再回來看看 ```Cpp= #include <algorithm> #include <iomanip> #include <iostream> #include <string> #include <vector> using namespace std; class Rational{ public: //constructor Rational(); Rational(int n); Rational(int n, int d); void show() const{ cout << numer << "/" << denom << endl; } // private: int numer; int denom; }; Rational::Rational(int n, int d){ numer = n; denom = d; } ``` ```Cpp= using namespace std; class Rational{ public: //constructor Rational() : numer{0}, denom{1} {} Rational(int n) : numer{n}, denom{1} {} Rational(int n, int d) : numer{n}, denom{d} {} void show() const{ cout << numer << "/" << denom << endl; } // private: int numer; int denom; }; ```