您好,登錄后才能下訂單哦!
這篇文章主要介紹C++中指針,引用和STL的示例分析,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!
對象的定義:對象是指一塊能存儲數(shù)據(jù)并具有某種類型的內(nèi)存空間
一個(gè)對象a,它有值和地址;運(yùn)行程序時(shí),計(jì)算機(jī)會為該對象分配存儲空間,來存儲該對象的值,通過該對象的地址,來訪問存儲空間中的值。
類型名 * 指針變量名;
每個(gè)變量都被存放在從某個(gè)內(nèi)存地址(以字節(jié)為單位)開始的若干個(gè)字節(jié)中;"指針",也稱作"指針變量",大小為4個(gè)字節(jié)(或8個(gè)字節(jié))的變量,其內(nèi)容代表一個(gè)內(nèi)存地址;通過指針,能夠?qū)υ撝羔樦赶虻膬?nèi)存區(qū)域進(jìn)行讀寫。
int * p; //p是一個(gè)指針,變量p的類型是int *
T * p; //T可以是任何類型的名字,比如int, double p 的類型: T* *p 的類型: T 通過表達(dá)式 *p,可以讀寫從地址p開始的sizeof(T)個(gè)字節(jié) *p 等價(jià)于存放在地址p處的一個(gè)T類型的變量 * 間接引用運(yùn)算符 sizeof(T*) 4字節(jié)(64位計(jì)算機(jī)上可能8字節(jié))
char ch2 = 'A' char *pc = &ch2; //使得pc指向變量ch2 &: 取地址運(yùn)算符 &x: 變量x的地址(即指向x的指針),對于類型為T的變量x,&x表示變量x的地址(即指向x的指針) &x的類型是T*
指針的作用
使用指針,就有自由訪問內(nèi)存空間的手段
不需要通過變量,就能對內(nèi)存直接進(jìn)行操作。通過指針,程序能訪問的內(nèi)存區(qū)域就不僅限于變量所占據(jù)的數(shù)據(jù)區(qū)域。
指針的相互賦值
不同類型的指針,如果不經(jīng)過強(qiáng)制類型轉(zhuǎn)換,不能直接互相賦值。
指針的運(yùn)算
兩個(gè)同類型的指針變量,可以比較大?。ū容^的是地址空間的大?。?/p>
兩個(gè)同類型的指針變量,可以相減(相減值為地址空間差值除以sizeof(T))
指針變量加減一個(gè)整數(shù)的結(jié)果是指針
p: T*類型的指針 n: 整數(shù)類型的變量或常量 p + n: T*類型的指針,指向地址(地址 p + n * sizeof(T)) n + p, p - n, *(p + n), *(p - n) 分別為地址和地址指向的值 eq: int a = 10; int b = 15; int * p = &a; //0x61fe04 int * q = &b; //0x61fe00 int * ans = p + 2; //0x61fe0c int k = *(p - 1); //15
指針變量可以自增、自減 (p++, ++p, p--, --p)即p指向的地址n + sizeof(T)或者n - sizeof(T)
指針可以用下標(biāo)運(yùn)算符"[]"進(jìn)行運(yùn)算
p是一個(gè)T*類型的指針 n是整數(shù)類型的變量或常量 p[n]等價(jià)于*(p + n)
空指針
地址0不能訪問。指向地址0的指針就是空指針
可以用"NULL"關(guān)鍵字對任何類型的指針進(jìn)行賦值。NULL實(shí)際上就是整數(shù)0,值為NULL的指針就是空指針
int *pn = NULL; char *pc = NULL; int *p2 = 0;
指針作為函數(shù)參數(shù)(形參是實(shí)參的一個(gè)拷貝)
指針和數(shù)組
數(shù)組的名字是一個(gè)指針常量(指向數(shù)組的起始地址)
T a[N]; a的類型是T* 可以用a給一個(gè)T*類型的指針賦值 a是編譯時(shí)其值就確定了的常量,不能夠?qū)進(jìn)行賦值
作為函數(shù)形參時(shí),T *p和 T p[]等價(jià)
void Func(int *p){ cout << sizeof(p); }void Func(int p[]){ cout << sizeof(p); }
類型名 & 引用名 = 某變量名;(定義了一個(gè)引用,將其初始化為引用某個(gè)變量)
int n = 4; int & r = n; //r引用了n, r的類型是int &v
某個(gè)變量的引用,等價(jià)于這個(gè)變量,相當(dāng)于該變量的一個(gè)別名
定義引用時(shí)一定要將其初始化成引用某個(gè)變量
初始化后,它就一直引用該變量,不會再引用別的變量
引用只能引用變量,不能引用常量和表達(dá)式
引用作為函數(shù)的返回值
int n = 4; int & SetValue() { return n; } int main() { SetValue() = 40; cout << n; //輸出是40 return 0; }
常引用
定義引用時(shí),前面加const關(guān)鍵字,即為"常引用"
int n; const int & r = n; //r的類型是const int &
不能通過常引用去修改其引用的內(nèi)容: int n = 100; const int & r = n; r = 200; //編譯錯(cuò)誤 n = 300; //ok
常引用和非常引用的轉(zhuǎn)換
const T &和 T &是不同的類型,T &類型的引用或T類型的變量可以用來初始化const T &類型的引用;const T類型的常變量和const T &類型的引用則不能用來初始化T &類型的引用。
容器(Container
),一種數(shù)據(jù)結(jié)構(gòu)(包含一組元素或元素集合的對象),基本容器:向量(vector), 雙端隊(duì)列(deque), 列表(list), 集合(set), 多重集合(multiset), 映射(map), 多重映射(multimap)。
序列式容器(Sequence containers
),其中每個(gè)元素均有固定位置--取決于插入時(shí)機(jī)和地點(diǎn),和元素值無關(guān)(vector, deque, list)
關(guān)聯(lián)式容器(Associative containers
),元素位置取決于特定的排序準(zhǔn)則以及元素值,和插入次序無關(guān)(set, multiset, map, multimap)
迭代器(Iterator)
迭代器Iterator,用來在一個(gè)對象集群(collection of objects)的元素上進(jìn)行遍歷。這個(gè)對象集群或許是一個(gè)容器,或許是容器的一部分。迭代器的主要好處是,為所有容器提供了一組很小的公共接口。迭代器以++進(jìn)行累進(jìn),以*進(jìn)行提領(lǐng),因而類似于指針,可以將其視為一種smart pointer。
例如++操作可以遍歷至集群內(nèi)的下一個(gè)元素。至于如何完成,取決于容器內(nèi)部的數(shù)據(jù)組織形式。
每種容器都提供自己的迭代器,而這些迭代器能夠了解容器內(nèi)部的數(shù)據(jù)結(jié)構(gòu)
算法(Algorithm)
用來處理群集內(nèi)的元素。它們可以出于不同的目的而搜尋、排序、修改、使用那些元素。通過迭代器的協(xié)助,我們可以只需編寫一次算法,就可以將它應(yīng)用于任意容器,這是因?yàn)樗械娜萜鞯鞫继峁┮恢碌慕涌凇?/p>
仿函數(shù)(Functor)
適配器(Adaptor)
提供三種順序容器適配器:queue(FIFO隊(duì)列),priority_queue(優(yōu)先級隊(duì)列),stack(棧)。
適配器對容器進(jìn)行包裝,使其表現(xiàn)出另外一種行為。倘若要使用適配器,需要加入頭文件
分配器(Allocator)
vector
一個(gè)數(shù)組必須有固定的長度,在開數(shù)組的時(shí)候,此長度就被靜態(tài)地確定下來。但vector卻是數(shù)組的"加強(qiáng)版",vector理解為一個(gè)"變長數(shù)組"
事實(shí)上,vector的實(shí)現(xiàn)方式是基于倍增思想的:假如vector的實(shí)際長度為n,m為vector當(dāng)前的最大長度,那么在加入一個(gè)元素的時(shí)候,先看一下,假如當(dāng)前的n=m,則再動態(tài)申請一個(gè)2m大小的內(nèi)存。反之,在刪除的時(shí)候,如果n≥m/2,則再釋放一半的內(nèi)存。
#include<vector> vector<int>vec; vector<pair<int, int> >vec_pair; struct node{ ... }; vector<node>vec_node;
vec.begin(), vec.end()
返回vector的首尾迭代器
vec.push_back()
從vector末尾加入一個(gè)元素
vec.size()
返回vector當(dāng)前的長度(大小)
vec.pop_back()
從vector末尾刪除一個(gè)元素
vec.empty()
返回vector是否為空,1為空,0不為空
vec.clear()
清空vector
vector容器是支持隨機(jī)訪問的,可以像數(shù)組一樣用[]取值。
vector<int>vec; vec.push_back(5); vec.push_back(2); cout << vec.back() << endl; for(vector<int>::iterator iter = vec.begin(); iter != vec.end(); iter++) { cout << *iter << endl; }
vector修改值
有迭代器,使用迭代器修改 auto iter = v.begin(), *iter = 1
使用索引進(jìn)行修改 v[0] = 1
deque(雙端隊(duì)列)
#include<deque>deque<int>q
q.begin(), q.end()
返回deque的首尾迭代器
q.front(), q.back()
返回deque的首尾元素
q.push_back()
從隊(duì)尾入隊(duì)一個(gè)元素
q.push_front()
從隊(duì)頭入隊(duì)一個(gè)元素
q.pop_back()
從隊(duì)尾出隊(duì)一個(gè)元素
q.pop_front()
從隊(duì)頭出隊(duì)一個(gè)元素
q.size()z
隊(duì)列中元素個(gè)數(shù)
q.clear()
清空隊(duì)列
deque支持隨機(jī)訪問,可以像數(shù)組下標(biāo)一樣取出其中的一個(gè)元素。即q[i]
deque容器可以被應(yīng)用到SPFA算法的SLF優(yōu)化:SPFA算法的優(yōu)化方式
set
set滿足互異性,set集合中的元素是默認(rèn)升序的(set容器自動有序和快速添加、刪除的性質(zhì)是由其內(nèi)部實(shí)現(xiàn):紅黑樹(平衡樹的一種))
#include<set> set<int>s set<pair<int, int> >s;
s.empty()
返回集合是否為空,是為1,否為0
s.size()
返回當(dāng)前集合的元素個(gè)數(shù)
s.clear()
清空當(dāng)前集合
s.begin(), s.end()
返回集合的首尾迭代器(迭代器是一種指針。這里需要注意的是,由于計(jì)算機(jī)區(qū)間“前閉后開”的結(jié)構(gòu),begin()函數(shù)返回的指針指向的的確是集合的第一個(gè)元素。但end()返回的指針卻指向了集合最后一個(gè)元素后面一個(gè)元素。)
s.insert(k)
集合中加入元素k
s.erase(k)
集合中刪除元素k
s.find(k)
返回集合中指向元素k的迭代器。如果不存在這個(gè)元素,就返回s.end(),這個(gè)性質(zhì)可以用來判斷集合中有沒有這個(gè)元素。
s.lower_bound()
返回集合中第一個(gè)大于等于關(guān)鍵字的元素
s.upper_bound()
返回集合中第一個(gè)嚴(yán)格大于關(guān)鍵字的元素
multiset(有序多重集合)
s.erase(k)
erase(k)
函數(shù)在set容器中表示刪除集合中元素k。但在multiset容器中表示刪除所有等于k的元素。
倘若只刪除這些元素中的一個(gè)元素
if((it = s.find(a)) != s.end()) s.erase(it); if中的條件語句表示定義了一個(gè)指向一個(gè)a元素的迭代器,如果這個(gè)迭代器不等于s.end(), 就說明這個(gè)元素的確存在,就可以直接刪除這個(gè)迭代器指向的元素。
s.count(k) count(k)函數(shù)返回集合中元素k的個(gè)數(shù),為multiset所獨(dú)有。
map
可以根據(jù)鍵值快速地找到這個(gè)映射出的數(shù)據(jù), map容器的內(nèi)部實(shí)現(xiàn)是一棵紅黑樹
#include<map> map<int, char> mp; 建立一個(gè)從整型變量到字符型變量的映射
map<int, char>mp; //插入 mp[1] = 'a'; mp.insert(map<int, char>::value_type(2, 'b')); mp.insert(pair<int, char>(3, 'c')); mp.insert(make_pair<int, char>(4, 'd')); //查找 mp[3] = 't'; //修改鍵值對中的值 map<int, char>::iterator iter; iter = mp.find(3); iter->second = 'y'; cout << iter->second << endl; //刪除 mp.erase(2); //刪除鍵值對 //遍歷 for(map<int, char>::iterator iter = mp.begin(); iter != mp.end(); iter++) { cout << iter->first << endl; cout << iter->second << endl; }
mp.begin(), mp.end()
返回首尾迭代器
mp.clear()
清空函數(shù)操作
mp.size()
返回容器大小
queue(FIFO)
#include<queue>queue<int>q;queue<pair<int, int> >q;#include<queue> queue<int>q; queue<pair<int, int> >q;
q.front(), q.back()
返回queue的首尾元素
q.push()
從queue末尾加入一個(gè)元素
q.size()
返回queue當(dāng)前的長度(大小)
q.pop()
從queue隊(duì)首刪除一個(gè)元素
q.empty()
返回queue是否為空,1為空,0不為空
priority_queue
優(yōu)先隊(duì)列在隊(duì)列的基礎(chǔ)上,將其中的元素加以排序。其內(nèi)部實(shí)現(xiàn)是一個(gè)二叉堆。優(yōu)先隊(duì)列即為將堆模板化,將所有入隊(duì)的元素排成具有單調(diào)性的一隊(duì),方便我們調(diào)用。
大根堆聲明就是將大的元素放在堆頂?shù)亩?。?yōu)先隊(duì)列默認(rèn)實(shí)現(xiàn)的就是大根堆。
小根堆聲明就是將小的元素放在堆頂?shù)亩选?/p>
#include<queue> priority_queue<int>q; //大根堆 priority_queue<string>q; priority_queue<pair<int, int> >q; priority_queue<int, vector<int>, less<int> >q; //大根堆 priority_queue<int, vector<int>, greater<int> >q; //小根堆
q.top()
返回priority_queue的首元素
q.push()
向priority_queue中加入一個(gè)元素
q.size()
返回priority_queue當(dāng)前的長度(大?。?/p>
q.pop()
從priority_queue末尾刪除一個(gè)元素
q.empty()
返回priority_queue是否為空,1為空,0不為空
stack(棧)
#include<stack>stack<int> st;stack<pair<int, int> > st;
st.top()
返回stack的棧頂元素
st.push()
從stack棧頂加入一個(gè)元素
st.size()
返回stack當(dāng)前的長度(大小)
st.pop()
從stack棧頂彈出一個(gè)元素
st.empty()
返回stack是否為空,1為空,0不為空
string(字符串操作)
其實(shí)string容器就是一個(gè)字符串
操作 | string | 字符陣列 |
聲明字符串 | string s | char s[100] |
取得第i個(gè)字符 | s[i] | s[i] |
字符串長度 | s.length(), s.size() | strlen(s) 不計(jì)\0 |
讀取一行 | getline(cin, s) | gets(s) |
設(shè)成某字符串 | s = "TCGS" | strcpy(s, "TCGS") |
字符串相加 | s = s + "TCGS" | strcat(s, "TCGS") |
字符串比較 | s == "TCGS" | strcmp(s, "TCGS") |
C++語言中已經(jīng)給出的運(yùn)算符(算數(shù)運(yùn)算符和邏輯運(yùn)算符)只是針對C++語言中已經(jīng)給定的數(shù)據(jù)類型進(jìn)行運(yùn)算。倘若我們想要對我們自定義數(shù)據(jù)類型進(jìn)行運(yùn)算的話,則需要重載運(yùn)算符,我們可以把重載運(yùn)算符理解為對已有的運(yùn)算符的一種重新定義。
重載運(yùn)算符的實(shí)現(xiàn)
語法格式如下 <返回類型> operator <運(yùn)算符符號>(<參數(shù)>) { <定義>; }
//定義結(jié)構(gòu)體 struct node { int id; double x, y; }; //重載運(yùn)算符"<" bool operator < (const node &a, const node &b) { if(a.x != b.x) return a.x < b.x; else return a.y < b.y; }
以上是“C++中指針,引用和STL的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。