一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - C/C++ - C++模板非類型形參的詳細講解

C++模板非類型形參的詳細講解

2022-02-24 14:29Jerish_C C/C++

這篇文章主要給大家介紹了關于C++模板非類型形參的相關資料,文中通過實例代碼介紹的非常詳細,對大家的學習或者工作就有一定的參考學習價值,需要的朋友可以參考下

前言

關于模板的非類型形參,網上有很多內容,C++primer只有大概一頁的闡述,但是都不夠清晰詳細。下面我盡可能從自己的角度去給大家描述一下非類型形參的相關細節。如果想進一步理解非類型形參以及模板內容可以閱讀C++template這本書,在4.1節,8.3.3節,13.2節都有相關解釋。

模板除了定義類型參數,我們還可以在模板定義非類型參數。

什么是非類型形參?顧名思義,就是表示一個固定類型的常量而不是一個類型。

先舉一個簡單的例子(模板類與模板函數都可以用非類型形參)

?
1
2
3
4
5
6
7
8
9
//例子1:
template<class T,int MAXSIZE> class List{
      private:
         T elems[MAXSIZE]; 
      public:
         Print(){ cout<<"The maxsize of list is"<<MAXSIZE; }
}
List<int,5> list;
list.Print();//打印"The maxsize of list is 5"

這個固定類型是有局限的,只有整形,指針和引用才能作為非類型形參,而且綁定到該形參的實參必須是常量表達式,即編譯期就能確認結果。

這里要強調一點,我們對于非類型形參的限定要分兩個方面看

1.對模板形參的限定,即template<>里面的參數

2.對模板實參的限定,即實例化時<>里面的參數

下面逐個解釋一下非類型形參的局限

1.浮點數不可以作為非類型形參,包括float,double。具體原因可能是歷史因素,也許未來C++會支持浮點數。

2.類不可以作為非類型形參。

3.字符串不可以作為非類型形參

4.整形,可轉化為整形的類型都可以作為形參,比如int,char,long,unsigned,bool,short(enum聲明的內部數據可以作為實參傳遞給int,但是一般不能當形參)

5.指向對象或函數的指針與引用(左值引用)可以作為形參

下面解釋一下非類型實參的局限

1.實參必須是編譯時常量表達式,不能使用非const的局部變量,局部對象地址及動態對象

2.非Const的全局指針,全局對象,全局變量(下面可能有個特例)都不是常量表達式。

3.由于形參的已經做了限定,字符串,浮點型即使是常量表達式也不可以作為非類型實參

備注:常量表達式基本上是字面值以及const修飾的變量

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//例子2:
template<class T,int MAXSIZE> class List{
private:
    T elems[MAXSIZE]; 
public:
    void Print(){ cout<<"The maxsize of list is "<<MAXSIZE; }
};
 
const int num1 = 9; ;//全局變量
static int num2= 9; ;//全局變量
const int num3 = 9; ;//局部變量
 
List<int,num1> list; //正確
List<int,num2> list; //錯誤
List<int,num3> list; //正確
 
//再看一個關于指針和字符串比較特別的例子
//例子3:
template<char const* name>
class pointerT{
 
};
 char a[] = "saaa";;//全局變量
 char a2[] = "saaa";;//局部變量,寫在main函數里面
 char *b = "saaa";//全局變量
 char *const c = "saaa";//全局變量,頂層指針,指針常量
 
 
pointerT<"testVarChar">  p1;//錯誤
 
pointerT<a>  p2;//正確
pointerT<a2>  p22;//錯誤,局部變量不能用作非類型參數
pointerT<b>  p3;//錯誤,error C2975:“pointerT”的模板參數無效,應為編譯時常量表達式
pointerT<c>  p4;//錯誤,error C2970: “c”: 涉及帶有內部鏈接的對象的表達式不能用作非類型參數

//關于指針常量和常量指針可以參考博客

Const用法總結(快速區分指針常量與常量指針)

這里大家可能會有幾個疑問

①.到底為什么字符串不能作為實參?

答:我們看到上面p1的模板實參是"testVarChar",然而當我們在另一個編譯單元(.cpp文件)同樣聲明這么一個模板實例時,這兩個"testVarChar"的地址可能是不同的,編譯器傳遞給模板時就會傳遞傳遞不同的地址,從而導致這兩個模板實例是兩個不同且不兼容的類型。這就是支持字符串的問題所在。(這里可能更深的涉及模板的實現原理)

②.變量b和c作為模板實參為什么錯誤不同?

答:首先解釋b實參,b在這里看做是一個指針,是一個全局指針,但是他不是一個常量表達式,所以b不對。我們再看看c,c相比于b對了一個const修飾符,表示這個指針是一個常量。然而const是一個比較特別的關鍵字,他具有內部鏈接屬性(關于內連接參考博客 理解C++的鏈接:C++內鏈接與外鏈接的意義),也就是說僅在定義這個變量的文件內可見,不會造成不同編譯單元的混編時的鏈接錯誤。

這個特性對于模板來說可是有問題的,就像問題①所描述的,由于每個編譯單元可能都有一個c變量,導致在編譯時,實例化多個c,而且c的地址還不同,這就造成二個模板的實例是兩個不同且不兼容的類型。

③為什么a變量作為實參可以?

答:我看過一些書籍,上面舉得例子都是用const修飾不行的情況下在加extern來形成extern constchara[]="saaa";這樣形式的語句,extern和const聯合使用確實可以壓制const的內部屬性。

這個a這里可以看做一個數組類型,進一步理解數組與指針的關系

附:char * itoa(int, char *, int); 第二個參數明明是char*,為什么卻又不能是“char*”?

Itoa這個函數大家應該多多少少接觸過,它的功能使把一個整型按照你給的進制轉換成你想要的字符串,也就是這個函數讓我覺得有必要再去研究一下字符串數組和字符串指針的區別。

首先看itoa這個函數原型,char * itoa(int originNum, char * targetStr, int standard);

第一個參數你的整型數據,第二個是一個字符串,第三個是一個int型表示N進制。

現在我們測試一下,

char *str=“hello”;

int num=123;

_itoa_s(num, str,10); //vs C++下使用會提示編譯錯誤

itoa(num,str,10);//codeblocks下運行會崩潰,正常環境下都會崩潰的

char str2[]=“hello”;

itoa(num, str2,10);//運行正常

這樣我們發現明明函數原型的參數就是char*,為什么我們寫的str卻不行呢?

char *和char[]到底有什么區別?

這里,我們先從其本質說起。說到底一個是數組一個是指針,兩者其實除了都能保存字符串外區別確實大了。最重要的一點區別就是內存分配(關于C語言變量在內存的存儲位置,大家可以參考…….),對于基本類型的單個變量與數組我們都會為其在棧上申請空間來存放數據,而指針只是指向一塊內存的索引,所以char*聲明的只是指向常量區”hello”的指針。

這時候我們再看一下itoa的功能,它是要把num轉換成字符串存在str里面,然而這時候我們的str根本沒有一塊可以用的內存,當然會崩潰。

反觀數組str2,在聲明的時候就已經在棧上分配內存了,這時候當然可以保存數據了。

因此,必須要為其分配內存

?
1
2
3
char *t;
 
t = (char*)malloc(9*sizeof(char));

接著上面的例子,我們需要理解

?
1
2
3
char *str=“hello”;
 
char str2[]=“hello”;

這是兩種不同的操作,str是聲明一個指針指向常量區的”hello”。而str2是聲明一個str2數組用來存放一個”hello”字符串的拷貝。總之,如果str動態申請內存的話,那么在堆里str指向的位置就會有一個”hello”,棧里面有str2指向的”hello”,常量區還有一個”hello”。雖然都是賦值,差距卻非常大。

下面一個例子進一步證明了這一點(vs2012):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
const char*s1= "sa1";
 
const char*s2= "sa1";
 
if(s1== "sa1")
 
{
 
         cout<<"ok";//打印ok
 
}
 
 
 
char *oname= (char*)malloc(6*sizeof(char));        
 
strcpy_s(oname,6,"hello");
 
cout<<oname;//打印hello
 
if(oname== "hello")
 
{
 
         cout<<oname;//不執行
 
}
 
 
 
char str2[]= "hello";
 
cout<<str2;//打印hello
 
if(str2== "hello")
 
{
 
         cout<<str2;//不執行
 
}

我們知道字符串比較不能用 == 直接比較,需要用strcmp,因為上面的s1,s2,oname,str2都是指針,比較其實只是比較指針的大小。我們看到,只有上面的 s1 == "sa1"結果是true。因為s1,s2指向的都是常量區的“sa1”字符串。oname,str2分別指向堆和棧區。

那么我們看到他不僅避免了①中的實例化地址不同的問題(因為是全局唯一的),而且還避免了const帶來的內部鏈接問題,所以這一項可能是經過編譯器優化過的結果。

總結

到此這篇關于C++模板非類型形參的文章就介紹到這了,更多相關C++模板非類型形參內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://blog.csdn.net/u012999985/article/details/50780311

延伸 · 閱讀

精彩推薦
  • C/C++C語言中炫酷的文件操作實例詳解

    C語言中炫酷的文件操作實例詳解

    內存中的數據都是暫時的,當程序結束時,它們都將丟失,為了永久性的保存大量的數據,C語言提供了對文件的操作,這篇文章主要給大家介紹了關于C語言中文件...

    針眼_6702022-01-24
  • C/C++深入理解goto語句的替代實現方式分析

    深入理解goto語句的替代實現方式分析

    本篇文章是對goto語句的替代實現方式進行了詳細的分析介紹,需要的朋友參考下...

    C語言教程網7342020-12-03
  • C/C++詳解c語言中的 strcpy和strncpy字符串函數使用

    詳解c語言中的 strcpy和strncpy字符串函數使用

    strcpy 和strcnpy函數是字符串復制函數。接下來通過本文給大家介紹c語言中的strcpy和strncpy字符串函數使用,感興趣的朋友跟隨小編要求看看吧...

    spring-go5642021-07-02
  • C/C++c++ 單線程實現同時監聽多個端口

    c++ 單線程實現同時監聽多個端口

    這篇文章主要介紹了c++ 單線程實現同時監聽多個端口的方法,幫助大家更好的理解和學習使用c++,感興趣的朋友可以了解下...

    源之緣11542021-10-27
  • C/C++C++之重載 重定義與重寫用法詳解

    C++之重載 重定義與重寫用法詳解

    這篇文章主要介紹了C++之重載 重定義與重寫用法詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下...

    青山的青6062022-01-04
  • C/C++學習C++編程的必備軟件

    學習C++編程的必備軟件

    本文給大家分享的是作者在學習使用C++進行編程的時候所用到的一些常用的軟件,這里推薦給大家...

    謝恩銘10102021-05-08
  • C/C++C/C++經典實例之模擬計算器示例代碼

    C/C++經典實例之模擬計算器示例代碼

    最近在看到的一個需求,本以為比較簡單,但花了不少時間,所以下面這篇文章主要給大家介紹了關于C/C++經典實例之模擬計算器的相關資料,文中通過示...

    jia150610152021-06-07
  • C/C++C語言實現電腦關機程序

    C語言實現電腦關機程序

    這篇文章主要為大家詳細介紹了C語言實現電腦關機程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    xiaocaidayong8482021-08-20
主站蜘蛛池模板: 日本道在线播放 | 亚洲性视频在线观看 | 国产视频久久 | 色视频久久 | 三级午夜宅宅伦不卡在线 | 日本综合在线观看 | 欧美一级高清免费a | 亚洲欧美午夜 | 国产精品亚洲w码日韩中文 国产精品香蕉在线观看不卡 | 久久精品免视看国产 | 5278欧美一区二区三区 | 精品欧美一区二区三区四区 | 舔逼 | 久久久无码精品亚洲欧美 | 国产综合久久久久久 | 91免费永久国产在线观看 | 亚洲日本中文字幕在线2022 | 2021年国内自拍 | 国产欧美日韩视频在线观看一区二区 | 9热在线精品视频观看 | 久久黄色小视频 | 国产精品理论片在线观看 | 美女女女女女女bbbbbb毛片 | 扒开大腿狠狠挺进视频 | 成人午夜在线视频 | 秘书在办公室疯狂被hd | 波多野结衣一区免费作品 | 韩国办公室激情 | 天美传媒传媒免费观看 | 国产馆在线观看免费的 | 久热人人综合人人九九精品视频 | 国产高清好大好夹受不了了 | 欧美视频精品一区二区三区 | 亚洲2023无矿砖码砖区 | 国产老妇 | 久99视频精品免费观看福利 | 色就色欧美综合偷拍区a | 亚洲成人第一 | 成人啪啪漫画羞羞漫画www网站 | 国产91一区二区在线播放不卡 | 日韩风月片 |