網站首頁 編程語言 正文
對象的定義:對象是指一塊能存儲數據并具有某種類型的內存空間
一個對象a,它有值和地址;運行程序時,計算機會為該對象分配存儲空間,來存儲該對象的值,通過該對象的地址,來訪問存儲空間中的值。
指針、引用
指針
類型名 * 指針變量名;
每個變量都被存放在從某個內存地址(以字節為單位)開始的若干個字節中;"指針",也稱作"指針變量",大小為4個字節(或8個字節)的變量,其內容代表一個內存地址;通過指針,能夠對該指針指向的內存區域進行讀寫。
int * p; //p是一個指針,變量p的類型是int *
T * p; //T可以是任何類型的名字,比如int, double p 的類型: T* *p 的類型: T 通過表達式 *p,可以讀寫從地址p開始的sizeof(T)個字節 *p 等價于存放在地址p處的一個T類型的變量 * 間接引用運算符 sizeof(T*) 4字節(64位計算機上可能8字節)
char ch1 = 'A' char *pc = &ch1; //使得pc指向變量ch1 &: 取地址運算符 &x: 變量x的地址(即指向x的指針),對于類型為T的變量x,&x表示變量x的地址(即指向x的指針) &x的類型是T*
指針的作用?
使用指針,就有自由訪問內存空間的手段
不需要通過變量,就能對內存直接進行操作。通過指針,程序能訪問的內存區域就不僅限于變量所占據的數據區域。
指針的相互賦值
不同類型的指針,如果不經過強制類型轉換,不能直接互相賦值。
指針的運算
- 兩個同類型的指針變量,可以比較大小(比較的是地址空間的大小)
- 兩個同類型的指針變量,可以相減(相減值為地址空間差值除以sizeof(T))
- 指針變量加減一個整數的結果是指針
p: T*類型的指針 n: 整數類型的變量或常量 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)
- 指針可以用下標運算符"[]"進行運算
p是一個T*類型的指針 n是整數類型的變量或常量 p[n]等價于*(p + n)
空指針?
地址0不能訪問。指向地址0的指針就是空指針
可以用"NULL"關鍵字對任何類型的指針進行賦值。NULL實際上就是整數0,值為NULL的指針就是空指針
int *pn = NULL; char *pc = NULL; int *p2 = 0;
指針作為函數參數(形參是實參的一個拷貝)
指針和數組
數組的名字是一個指針常量(指向數組的起始地址)
T a[N]; a的類型是T* 可以用a給一個T*類型的指針賦值 a是編譯時其值就確定了的常量,不能夠對a進行賦值
作為函數形參時,T *p和 T p[]等價
void Func(int *p){ cout << sizeof(p); }void Func(int p[]){ cout << sizeof(p); }
引用
類型名 & 引用名 = 某變量名;(定義了一個引用,將其初始化為引用某個變量)
int n = 4; int & r = n; //r引用了n, r的類型是int &v
某個變量的引用,等價于這個變量,相當于該變量的一個別名
- 定義引用時一定要將其初始化成引用某個變量
- 初始化后,它就一直引用該變量,不會再引用別的變量
- 引用只能引用變量,不能引用常量和表達式
引用作為函數的返回值
int n = 4; int & SetValue() { return n; } int main() { SetValue() = 40; cout << n; //輸出是40 return 0; }
常引用
定義引用時,前面加const關鍵字,即為"常引用"
int n; const int & r = n; //r的類型是const int &
不能通過常引用去修改其引用的內容: int n = 100; const int & r = n; r = 200; //編譯錯誤 n = 300; //ok
常引用和非常引用的轉換
const T &和 T &是不同的類型,T &類型的引用或T類型的變量可以用來初始化const T &類型的引用;const T類型的常變量和const T &類型的引用則不能用來初始化T &類型的引用。
STL
STL中六大組件
容器(Container
),一種數據結構(包含一組元素或元素集合的對象),基本容器:向量(vector), 雙端隊列(deque), 列表(list), 集合(set), 多重集合(multiset), 映射(map), 多重映射(multimap)。
序列式容器(Sequence containers
),其中每個元素均有固定位置--取決于插入時機和地點,和元素值無關(vector, deque, list)
關聯式容器(Associative containers
),元素位置取決于特定的排序準則以及元素值,和插入次序無關(set, multiset, map, multimap)
迭代器(Iterator)
迭代器Iterator,用來在一個對象集群(collection of objects)的元素上進行遍歷。這個對象集群或許是一個容器,或許是容器的一部分。迭代器的主要好處是,為所有容器提供了一組很小的公共接口。迭代器以++進行累進,以*進行提領,因而類似于指針,可以將其視為一種smart pointer。
例如++操作可以遍歷至集群內的下一個元素。至于如何完成,取決于容器內部的數據組織形式。
每種容器都提供自己的迭代器,而這些迭代器能夠了解容器內部的數據結構
算法(Algorithm)
用來處理群集內的元素。它們可以出于不同的目的而搜尋、排序、修改、使用那些元素。通過迭代器的協助,我們可以只需編寫一次算法,就可以將它應用于任意容器,這是因為所有的容器迭代器都提供一致的接口。
仿函數(Functor)
適配器(Adaptor)
提供三種順序容器適配器:queue(FIFO隊列),priority_queue(優先級隊列),stack(棧)。
適配器對容器進行包裝,使其表現出另外一種行為。倘若要使用適配器,需要加入頭文件
分配器(Allocator)
常用容器用法介紹
vector
一個數組必須有固定的長度,在開數組的時候,此長度就被靜態地確定下來。但vector卻是數組的"加強版",vector理解為一個"變長數組"
事實上,vector的實現方式是基于倍增思想的:假如vector的實際長度為n,m為vector當前的最大長度,那么在加入一個元素的時候,先看一下,假如當前的n=m,則再動態申請一個2m大小的內存。反之,在刪除的時候,如果n≥m/2,則再釋放一半的內存。
#includevector vec; vector >vec_pair; struct node{ ... }; vector vec_node;
vec.begin(), vec.end()?
? ? ? 返回vector的首尾迭代器
vec.front(), vec.back()? ? ? ? 返回vector的首尾元素
vec.push_back()?
? ? ? ? ? ? ? 從vector末尾加入一個元素
vec.size()?
? ? ? 返回vector當前的長度(大小)
vec.pop_back()?
? ? ? 從vector末尾刪除一個元素
vec.empty()? ?
? ? 返回vector是否為空,1為空,0不為空
vec.clear()? ?
? ? 清空vector? ? ? ? ? ? ?
vector容器是支持隨機訪問的,可以像數組一樣用[]取值。? ?
vectorvec; vec.push_back(5); vec.push_back(2); cout << vec.back() << endl; for(vector ::iterator iter = vec.begin(); iter != vec.end(); iter++) { cout << *iter << endl; }
vector修改值?
- 有迭代器,使用迭代器修改? ? ? ? auto iter = v.begin(),? ? ? ? *iter = 1
- 使用索引進行修改? ? v[0] = 1
deque(雙端隊列)
#include<deque>deque<int>q
q.begin(), q.end()? ?
? ? 返回deque的首尾迭代器
q.front(), q.back()?
? ? ? 返回deque的首尾元素
q.push_back()?
? ? ? 從隊尾入隊一個元素
q.push_front()
? ? ? ? 從隊頭入隊一個元素
q.pop_back()? ? ?
? 從隊尾出隊一個元素
q.pop_front()?
? ? ? 從隊頭出隊一個元素
q.size()z
? ? ? ? 隊列中元素個數
q.clear()? ?
? ? 清空隊列
deque支持隨機訪問,可以像數組下標一樣取出其中的一個元素。即q[i]
deque容器可以被應用到SPFA算法的SLF優化:SPFA算法的優化方式
set
set滿足互異性,set集合中的元素是默認升序的(set容器自動有序和快速添加、刪除的性質是由其內部實現:紅黑樹(平衡樹的一種))
#includeset s set >s;
s.empty()?
? ? ? 返回集合是否為空,是為1,否為0
s.size()?
? ? ? 返回當前集合的元素個數
s.clear()? ? ?
? 清空當前集合
s.begin(), s.end()
? ? ? ? 返回集合的首尾迭代器(迭代器是一種指針。這里需要注意的是,由于計算機區間“前閉后開”的結構,begin()函數返回的指針指向的的確是集合的第一個元素。但end()返回的指針卻指向了集合最后一個元素后面一個元素。)?
s.insert(k)
? ? ? ? 集合中加入元素k
s.erase(k)? ?
? ? 集合中刪除元素k
s.find(k)???????
?返回集合中指向元素k的迭代器。如果不存在這個元素,就返回s.end(),這個性質可以用來判斷集合中有沒有這個元素。
s.lower_bound()? ? ?
? 返回集合中第一個大于等于關鍵字的元素
s.upper_bound()? ?
? ? 返回集合中第一個嚴格大于關鍵字的元素
multiset(有序多重集合)
s.erase(k)? ?
? ?
erase(k)
函數在set容器中表示刪除集合中元素k。但在multiset容器中表示刪除所有等于k的元素。
倘若只刪除這些元素中的一個元素
if((it = s.find(a)) != s.end()) s.erase(it); if中的條件語句表示定義了一個指向一個a元素的迭代器,如果這個迭代器不等于s.end(), 就說明這個元素的確存在,就可以直接刪除這個迭代器指向的元素。
s.count(k)? ? ? ? count(k)函數返回集合中元素k的個數,為multiset所獨有。?
map
可以根據鍵值快速地找到這個映射出的數據, map容器的內部實現是一棵紅黑樹
#include
mapmp; //插入 mp[1] = 'a'; mp.insert(map ::value_type(2, 'b')); mp.insert(pair (3, 'c')); mp.insert(make_pair (4, 'd')); //查找 mp[3] = 't'; //修改鍵值對中的值 map ::iterator iter; iter = mp.find(3); iter->second = 'y'; cout << iter->second << endl; //刪除 mp.erase(2); //刪除鍵值對 //遍歷 for(map ::iterator iter = mp.begin(); iter != mp.end(); iter++) { cout << iter->first << endl; cout << iter->second << endl; }
mp.begin(), mp.end()?
? ? ? 返回首尾迭代器?
mp.clear()
? ? ? ? 清空函數操作
mp.size()?
? ? ? 返回容器大小
queue(FIFO)
#includequeue q;queue >q;#include queue q; queue >q;
q.front(), q.back()?
? ? ? 返回queue的首尾元素
q.push()?
? ? ? 從queue末尾加入一個元素
q.size()? ?
? ? 返回queue當前的長度(大小)
q.pop()? ?
? ? 從queue隊首刪除一個元素
q.empty()?
? ? ? 返回queue是否為空,1為空,0不為空
priority_queue
優先隊列在隊列的基礎上,將其中的元素加以排序。其內部實現是一個二叉堆。優先隊列即為將堆模板化,將所有入隊的元素排成具有單調性的一隊,方便我們調用。
大根堆聲明就是將大的元素放在堆頂的堆。優先隊列默認實現的就是大根堆。
小根堆聲明就是將小的元素放在堆頂的堆。
#includepriority_queue q; //大根堆 priority_queue q; priority_queue >q; priority_queue , less >q; //大根堆 priority_queue , greater >q; //小根堆
q.top()?
? ? ? 返回priority_queue的首元素
q.push()?
? ? ? 向priority_queue中加入一個元素
q.size()?
? ? ? 返回priority_queue當前的長度(大小)
q.pop()
? ? ? ? 從priority_queue末尾刪除一個元素
q.empty()?
? ? ? 返回priority_queue是否為空,1為空,0不為空?
stack(棧)
#include<stack>stack<int> st;stack<pair<int, int> > st;
st.top()? ?
? ? 返回stack的棧頂元素
st.push()?
? ? ? 從stack棧頂加入一個元素
st.size()? ?
? ? 返回stack當前的長度(大小)
st.pop()? ?
? ? 從stack棧頂彈出一個元素
st.empty()? ? ?
? 返回stack是否為空,1為空,0不為空
string(字符串操作)
其實string容器就是一個字符串
操作 | string | 字符陣列 |
聲明字符串 | string s | char s[100] |
取得第i個字符 | s[i] | s[i] |
字符串長度 | s.length(), s.size() | strlen(s) 不計\0 |
讀取一行 | getline(cin, s) | gets(s) |
設成某字符串 | s = "TCGS" | strcpy(s, "TCGS") |
字符串相加 | s = s + "TCGS" | strcat(s, "TCGS") |
字符串比較 | s == "TCGS" | strcmp(s, "TCGS") |
重載運算符
C++語言中已經給出的運算符(算數運算符和邏輯運算符)只是針對C++語言中已經給定的數據類型進行運算。倘若我們想要對我們自定義數據類型進行運算的話,則需要重載運算符,我們可以把重載運算符理解為對已有的運算符的一種重新定義。
重載運算符的實現
語法格式如下 <返回類型> operator <運算符符號>(<參數>) { <定義>; }
//定義結構體 struct node { int id; double x, y; }; //重載運算符"<" bool operator < (const node &a, const node &b) { if(a.x != b.x) return a.x < b.x; else return a.y < b.y; }
總結
原文鏈接:https://blog.csdn.net/jiangchao98/article/details/123048206
相關推薦
- 2022-06-13 Python+Matplotlib繪制雙y軸圖像的示例代碼_python
- 2022-04-07 C#實現Socket服務器及多客戶端連接的方式_C#教程
- 2022-09-07 詳解C語言結構體,枚舉,聯合體的使用_C 語言
- 2022-12-04 Python?棧實現的幾種方式及優劣詳解_python
- 2022-06-19 Rainbond云原生快捷部署生產可用的Gitlab步驟詳解_云其它
- 2022-04-01 exception occurred during ITK-SNAP startup itk-sn
- 2023-03-28 react-redux的connect示例詳解_React
- 2023-02-09 Flask如何獲取用戶的ip,查詢用戶的登錄次數,并且封ip_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支