auto類型推導的文法和規則
auto 要求必須對變量進行初始化
int x = 0;
auto *p1 = &x; //p1 為 int *,auto 推導為 int
auto p2 = &x; //p2 為 int*,auto 推導為 int*
auto &r1 = x; //r1 為 int&,auto 推導為 int
auto r2 = r1; //r2 為 int,auto 推導為 int
auto與const結合
int x = 0;
const auto n = x; //n 為 const int ,auto 被推導為 int
auto f = n; //f 為 const int,auto 被推導為 int(const 屬性被抛棄)
const auto &r1 = x; //r1 為 const int& 類型,auto 被推導為 int
auto &r2 = r1; //r1 為 const int& 類型,auto 被推導為 const int 類型
最後我們來簡單總結一下 auto 與 const 結合的用法:
當類型不為引用時,auto 的推導結果将不保留表達式的 const 屬性;
當類型為引用時,auto 的推導結果将保留表達式的 const 屬性。
auto 用于泛型程式設計
auto 的另一個應用就是當我們不知道變量是什麼類型,或者不希望指明具體類型的時候,比如泛型程式設計中。我們接着看例子:
#include <iostream>
using namespace std;
class A{
public:
static int get(void){
return 100;
}
};
class B{
public:
static const char* get(void){
return "http://c.biancheng.net/cplus/";
}
};
template <typename T>
void func(void){
auto val = T::get();
cout << val << endl;
}
int main(void){
func<A>();
func<B>();
return 0;
}
運作結果:
100
http://c.biancheng.net/cplus/
using定義别名(替代typedef)
C98
template <typename Val>
struct str_map
{
typedef std::map<std::string, Val> type;
};
str_map<int>::type map1;
C++11
template <typename Val>
using str_map_t = std::map<std::string, Val>;
str_map_t<int> map1;
// 重定義unsigned int
typedef unsigned int uint_t;
using uint_t = unsigned int;
// 重定義std::map
typedef std::map<std::string, int> map_int_t;
using map_int_t = std::map<std::string, int>;
C++11 tuple元組詳解
struct person{
char *m_name;
char *m_addr;
int *m_ages;
};
//使用tuple來表示這樣一個結構體,作用是一樣的
std::tuple<const char *,const char *,int>
Lambda表達式
Lambda 表達式的 [] 用來确定捕獲參數:
1.[=]:捕獲的局部變量隻可讀不可寫,捕獲範圍是目前 Lambda 表達式之前的作用域。
2.[&]:捕獲的局部變量可讀可寫。
[ capture ] ( params ) opt -> ret { body; };
void MyClass::function() {
// 使用 [this] 來捕獲 this
auto fun1 = [this](int v){cout << v + this->num << endl; };
// 使用 [&] 捕獲所有父作用域的引用,包括 this
auto fun2 = [&](int v){cout << v + this->num << endl; };
}
int main(void) {
int num = 100;
// read only
auto fun1 = [=](){ cout << num << endl; };
fun1();
// read and write
auto fun2 = [&num](){ num = 200; cout << num << endl; };
fun2();
// num = 200
cout << num << endl;
return 0;
}
---------------------------------------------------------------------------
//周遊
int main() {
vector<int> vec = {1, 2, 3, 4, 5};
// 定義 Lambda
auto fun = [](int num){ cout << num << endl;}
for_each(vec.begin(), vec.end(), fun);
// 将 vec 中的元素都加 1,修改參數必須傳遞參數的引用
for_each(vec.begin(), vec.end(), [](int& num){ num += 1;});
for_each(vec.begin(), vec.end(), fun);
return 0;
}
auto f = [](int a) -> int { return a + 1; };
std::cout << f(1) << std::endl; // 輸出: 2
for循環
//for循環周遊普通數組
for (char ch : arc) {
cout << ch;
}
//for循環周遊 vector 容器
for (auto ch : myvector) {
cout << ch;
}
//{}的使用
for (int num : {1, 2, 3, 4, 5}) {
cout << num << " ";
}
//for循環周遊并修改容器中各個字元的值
for (auto &ch : myvector) {
ch++;
}
右值引用
2 個 ‘&’ 表示右值引用。
int num = 10;
//int && a = num; //右值引用不能初始化為左值
int && a = 10;
某些場景中,我們可能需要限制調用成員函數的對象的類型(左值還是右值)所謂引用限定符,就是在成員函數的後面添加 “&” 或者 “&&”,進而限制調用者的類型(左值還是右值)
#include <iostream>
using namespace std;
class demo {
public:
demo(int num):num(num){}
int get_num()&{
return this->num;
}
private:
int num;
};
int main() {
demo a(10);
cout << a.get_num() << endl; // 正确
//cout << move(a).get_num() << endl; // 錯誤
return 0;
}
nullptr:初始化空指針
實際開發中,避免産生野指針最有效的方法,就是在定義指針的同時完成初始化操作,即便該指針的指向尚未明确,也要講其初始化空指針。
int * a1 = nullptr;
char * a2 = nullptr;
double * a3 = nullptr;
shared_ptr智能指針
程式突然崩潰、程式運作所用記憶體越來越多最終不得不重新開機,往往都是記憶體資源管理不當造成。
1.有些資源已經被釋放,但指向它的指針并沒有改變指向(成了野指針),并且後續還在使用;
2.有些記憶體資源已經被釋放,後期又試圖在釋放一次(重複釋放統一記憶體會導緻程式運作崩潰);
3.沒有及時釋放不在使用的記憶體資源,造成記憶體洩露,程式占用的記憶體資源越來越多。
std::shared_ptr<int> p1; //不傳入任何實參
std::shared_ptr<int> p2(nullptr); //傳入空指針 nullptr
std::shared_ptr<int> p3(new int(10));
std::shared_ptr<int> p3 = std::make_shared<int>(10);
//調用拷貝構造函數
std::shared_ptr<int> p4(p3);//或者 std::shared_ptr<int> p4 = p3;
//調用移動構造函數
std::shared_ptr<int> p5(std::move(p4)); //或者 std::shared_ptr<int> p5 = std::move(p4);
unique_ptr
unique_ptr<string> p3(new string("auto"));
unique_ptr<string> p4;
p4=p3;//此時會報錯