程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++ template的一些高級用法(元編碼,可變參數,仿函數,using使用方法,. C++ 智能指針)

C++ template的一些高級用法(元編碼,可變參數,仿函數,using使用方法,. C++ 智能指針)

編輯:C++入門知識

C++ template的一些高級用法(元編碼,可變參數,仿函數,using使用方法,. C++ 智能指針)


1 .  通用函數可變參數模板        對於有些時候,我們無法確切的知道,函數的參數個數時,而又不想過多的使用所謂的函數重載,那麼就可以效仿下面的例子:      1 #include<iostream>  2 #include<Array>  3 void showall() { return; }  4   5 template <typename R1 ,typename...  Args>  6   7 void showall(R1 var, Args...args) {  8   9     std::cout << var << std::endl; 10     showall(args...); 11 } 12  13 int main(int argc, char * args[]) { 14  15      16     showall(1, 2, 3, 4, 5); 17     showall("gxjun","dadw","dasds"); 18     showall(1.0,2.0,3.5); 19     std::cin.get(); 20     return 0; 21 }   在游戲開發中,時常會用到這樣的模板,類型不確定,參數的個數不確定,所以需要用一種類似於遞歸的函數來處理。  第一個函數,表示的是在參數為0時,結束。           2.  如何使用仿函數:        首先仿函數的定義: ,仿函數也叫函數對象(Function Object, or Functor),定義就是任何可以像函數一樣被調用的對象。一個普通的函數是函數對象,一個函數指針當然也是,廣義上說任何定義了operator()的類對象都可以看作是函數對象。 (找到文檔)         其實,往直白的地方說,就是一個不是函數但是具有函數功能且用法和函數相同的對象(結構體或者類)。   下面舉個栗子(用結構體實現函數功能):           1 /*關於C++仿函數*/  2 #include<iostream>  3 #include<functional>  4 using namespace std;  5 using namespace std::placeholders;    6   7 template <typename R1 , typename R2>  8 struct  Calc  9 { 10     void add(R1 a) { 11         cout << a << endl; 12     }; 13     void add_1(R1 a, R1 b) { 14         cout << a + b << endl; 15     }   16 }; 17  18 int main(int argc, char * args[]) { 19  20     //函數指針 21     void(Calc<int, double>::*fc)(int  a) = &Calc<int, double >::add; 22     // fc(25); 23     //顯然上面的式子比較的麻煩 24      25     Calc < int, int> calc; 26     auto  fun = bind(&Calc<int, int >::add, &calc, _1); 27     auto  fun_2 = bind(&Calc<int, int >::add_1, &calc, _1,_2); 28     fun(123); 29     fun_2(12,24); 30    cin.get(); 31  return 0; 32 }       對於bind()這個函數,開頭的是地址,函數名,後面的是第一個列子中的Args....不定參數類型、           3. 使用using別名,函數指針,typdef來實現函數的調用       雖然是寥寥的幾行代碼,但是功能在實際應用中,卻會發揮很大的作用。      1 //using別名使用用法  2 #include<iostream>  3 #include<windows.h>  4 int calc() {  5   //當為無參數時,返回0值  6     return 0;  7 }  8   9 template <typename R1 ,typename...Args> 10 int calc(R1 a, Args...args) { 11  12     return a + calc(args...); 13 } 14  15 int main(int argc , char * args []) { 16  17     //使用函數指針 18     int(*fun) (int ,int ,int ,int ) = calc; 19     system("echo 使用函數指針實現1~4累加"); 20     std::cout << fun(1,2,3,4)<<std::endl; 21    //使用typedef來實現該功能 22     system("echo 使用typedef實現1~4累加"); 23      typedef int(*Add)(int, int, int); 24      Add  Gadd = calc; 25      std::cout << Gadd(1, 2, 3) << std::endl; 26     //使用using別名來實現這麼個功能 27     system("echo 使用using實現1~4累加"); 28     using Func = int(*) (int, int, int, int); 29     Func func = calc; 30     std::cout << func(1, 2, 3, 4) << std::endl; 31     std::cin.get(); 32  return 0; 33 }       4. C++模板元編程:             對於模板元編程: 我的理解是,你所要的計算,在編譯的時候,已經處理玩了,只需要在運行的時候輸出結果即可!       當我們每每學到模板元編程的時候,就會有一個混淆的詞匯出現,哒,看------函數式編程。 到底什麼是函數式編程呢?       建議去看這篇文章,   模板元編程用處廣泛,       我們知道當硬件條件限制的情況下,除了優化算法,還有一種途徑,那就是用模板元編程。 現在就讓我們來看看這個金典的應用吧!       斐波那契數列的計算......            1 #include<iostream>  2 #include<time.h>  3 #include<windows.h>  4 /*  5   斐波那契數列  6    H(1)=H(0)=1;  7    H(N)= H(N-1)+H(N-2);  8 */  9 using namespace std; 10  11  /* 普通版普通版 */ 12  using _int = long  ;    //使用別名 13   14  _int feibona(_int ac) { 15     if (ac == 0||ac==1)  return 1; 16     return feibona(ac-1) +feibona(ac-2); 17 } 18  19  /* 使用元編程 完全特化版 方法如下*/ 20  template <_int N> 21  struct data { 22      //采用枚舉 23      enum { res = data<N - 1>::res + data<N - 2>::res }; 24  }; 25  26 template <> 27 struct data<1> { 28     //采用枚舉 29     enum { res = 1L }; 30 }; 31  32 template <> 33 struct data<0> { 34     //采用枚舉 35     enum { res = 1L }; 36 }; 37  38  39 int main(int argc, char * args[]) { 40  41     time_t  a ,b; 42     a = clock(); //開始記錄時間 43     cout << data<45L>::res << endl; 44     b = clock(); //開始記錄時間 45     system("echo 采用元編程所消耗的時間"); 46     cout << (double)(b - a) / CLK_TCK<<"ms"<<endl; 47     a = clock(); 48     cout << feibona(45L) << endl; 49     b = clock(); 50     system("echo 采用普通的算法所消耗的時間"); 51     cout << (double)(b - a) / CLK_TCK << "ms" << endl; 52     cin.get(); 53     return 0; 54 }       5  C++智能指針 ,關於智能指針和普通指針,的幾種行為的對比          1 /*  2  智能指針:  3     對於C++而言:        std::auto_ptr<double> ptr(new double);  4     對於C++11新的智能指針:         std::unique_ptr<double>  ps(new double);  5     通過下面幾組數據做些一點  6 */  7 #include<iostream>  8 #include<memory>  9 #include<windows.h> 10 using  namespace std; 11 /*模式一 分配內存地址,而不手動進行回收 */ 12 void showp() { 13     system("echo 分配內存地址,而不手動進行回收"); 14     for (int i = 0; i < 10000000; i++) { 15           double * p = new double;   //不釋放 16     } 17     cin.get(); 18 } 19 /* 模式二,分配地址,並手動進行回收地址 */ 20 void showp1() { 21     system("echo 分配地址,並手動進行回收地址"); 22     for (int i = 0; i < 10000000; i++) { 23         double * p = new double;   //不釋放 24         delete p; 25     } 26     cin.get(); 27  28 } 29 /*模式三,分配地址,采用c++通用指針*/ 30 void showp2() { 31     system("echo 分配地址,采用c++通用指針"); 32  33     for (int i = 0; i < 10000000; i++) { 34         double * p = new double;   //不釋放 35         auto_ptr<double> ps(p);   //采用智能指針,不會多釋放地址,舊版本vc98支持 36     } 37     cin.get(); 38 } 39 /* 模式四,分配地址,采用C++11新型指針 */ 40  41 void showp3() { 42  43     system("echo 分配地址,采用C++11新型指針"); 44     for (int i = 0; i < 10000000; i++) { 45         auto_ptr<double> ps(new double);   //采用智能指針,C++11新特性 46     } 47     cin.get(); 48 } 49  50 int main(int argc , char * args []) { 51   52     //auto_ptr 53    //函數指針 54     void(*p[])() = { showp,showp1,showp2,showp3 }; 55     //for (auto data : p) { 56     //    data(); 57    //} 58     p[1](); 59     system("echo 按一下結束"); 60     cin.get(); 61   return 0; 62 }       使用智能指針的好處:       1 、 不會對一個分配的地址,釋放兩次。如果手動釋放地址,存在著重復釋放或者漏放的情況。 避免內存洩露。         2.  釋放及時,不會搗鼓電腦中cpu換句話說,不會吃cpu。而是電腦運緩慢....    

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved