天天看點

C++11--學習簡記

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;//此時會報錯
           

繼續閱讀