C++:随笔3--复杂的数据结构
所謂函數(shù)重載的實質(zhì)就是用同樣的名字再定義一個有著不同參數(shù)但有著同樣用途的函數(shù)。(多重身份)(有著同樣的函數(shù)名但是參數(shù)不同(但是不能通過返回值不同來重載函數(shù)))
注意:可以是參數(shù)個數(shù)上的不同,也可以是參數(shù)數(shù)據(jù)類型上的不同。(同樣一個函數(shù)名實現(xiàn)的是同一個功能)
"<<"這個操作符在C中是左移操作符,但是在C++中是流操作符,就是被cout這個對象給重載了,
溫度轉(zhuǎn)換的函數(shù)重載例子:
?
----復(fù)雜的數(shù)據(jù)類型
int num[i];
for(i=0;i<10;i++)
{ cout<<"請輸入元素第"<<i+1<<"個元素"<<endl;cin>>num[i];//將輸入流向num[i]
}
int total=0;//int total;//如果只定義不進行初始化會產(chǎn)生異常數(shù)據(jù)。//因為他是個局部變量,
CPU認識的只是1和0;
三種數(shù)據(jù)類型:數(shù)組、指針、結(jié)構(gòu)。
-----數(shù)組
數(shù)組可以把許多個同類型的數(shù)值存儲在同一個變量名下。(數(shù)組仍需要被聲明為某一種特定的類型)
type name[i];
(局部變量,內(nèi)存不足夠幫你初始化,局部變量是存放在棧里面的,棧里面的數(shù)據(jù)是千變?nèi)f化的,他初始化不了,會隨機給一個很大的值,所以我們應(yīng)該在定義局部變量時進行初始化。)
宏定義和靜態(tài)變量:(都行)
#define ITEM 10
const unsigned short ITEM 10;
cin輸入正確的話返回值為0.
while(!0(cin>>nun[i]))
{cin.clear();//清除輸入緩沖區(qū)cin.ignore(100,"\n");cout<<"輸入錯誤"<<endl;
}
C語言中定義字符串:char? a[]="avsgdj";
C++中還可以使用:std::string類型。
#include<string>//字符串頭文件
int main()
{std::string str;//定義一個字符串變量str,注意把命名空間也得引入進來,他也是在std這個命名空間里面。std::cout<<"請隨便輸入一個字符串";//std::cin>>str;//接收輸入,存入到字符串str里面去。//cin遇到空格就以為輸入的字符串結(jié)束了(acd sdc dfe比如輸入三個中間有空格那么cin就只會接收acd后邊遇到空格就以為輸入的字符串結(jié)束了),所以下邊使用getline();接收字符串std::getline(std::cin,str);//用cin的方式存放到str里面去std::cout<<str<<"\n";//再把字符串輸出。return 0;
}
C++中的std::string(標準類)的類型其實是在C++標準庫定義的一個對象,其內(nèi)建功能非常多。
關(guān)于string的內(nèi)部方法:
提取子字符串;
比較字符串;
添加字符串;
搜索字符串;
等等;
----指針((地址是內(nèi)存里面的地址))
普通變量里面存放的是一個值,是數(shù)值;而指針變量里面存放的是地址。指針的類型必須與由他保存其地址的變量的類型一致。
程序在硬盤上以文件的形式存在,但他們的運行卻是在計算機的內(nèi)存里發(fā)生的(沒了內(nèi)存單靠硬盤和CPU是無法運行的,CPU是無法從硬盤上直接來進行運算,通過內(nèi)存作為這個中間件)。
//以下這些語句聲明的變量,在內(nèi)存中的存放情況。
int a=-12;
char b=M;
float c=3.14;
內(nèi)存圖示:
? ?
那剛才我們申明的這個變量它在內(nèi)存中是如何排放的,(a是整型占了4個字節(jié),字符型是占一個字節(jié))變量名事實上是給編譯器知道的,編譯器直接就會在整個程序里面將這個名稱和地址直接掛鉤(在內(nèi)存沒有存放他的名字)。
對齊:浮點型變量c的值為什么是從內(nèi)存地址8處開始存儲,而不是從內(nèi)存地址5處開始存儲?
(在c++里面,變量類型是根據(jù)他們的自然邊界進行對齊的(什么是自然邊界呢,一般是向CPU看齊,一個字節(jié)等于8位)(這個對齊可以不用管,編譯器會自動幫我們處理這類問題,我們只用定義變量給他賦值就好了))
尋址:(內(nèi)存里面就是地址和地址存放的數(shù)據(jù),變量名是給編譯器說的,編譯器在背后會給地址和變量名掛鉤起來,翻譯之后變量名都會變成地址)對于變量可以使用兩種方法來對它進行索引。
第一種是通過變量名,比如定義a=-12;如果我們輸出的話就直接通過變量名進行就可以了。
另一種是通過地址,地址是更為真實的。(其實變量名在最后編譯鏈接之后會變成一個地址)
取址操作符:&。作用獲取變量的地址。比如
int a=3;//定義一個變量a他的值是3;
cout<<"該變量的地址是:"<<&a;//把這個地址輸出出來直接就是在變量名前加上&符號。(小Q問:這個地址取的是上邊圖中左邊一欄的地址嗎?)這里輸出的就是這個變量程序運行之后他所占據(jù)的一個64位,8個字節(jié)的地址。
小Q問個問題哈:定義一個變量比如Int?a=5;對變量值進行訪問可以使用兩種方式,第一種是通過變量名。第二種是通過地址。之前說過變量名在進行編譯和鏈接之后也會變成一個地址,那么這個地址跟上邊存儲變量值的地址是同一個嗎?
小O答:是的,肯定是同一個地址,因為他們都指代同一塊內(nèi)存。
? ?
地址是計算機內(nèi)存中的某個位置,而指針是專門用來存放地址的特殊類型變量。
聲明指針變量的形式type? *pointerName;//指針的類型? *指針的名字;//(指針變量里面存放的就是地址)
int *p1,p2,p3;//這個定義的指針變量只有一個p1,而p2和p3都是整型變量。
int *p1,*p2,*p3;//這才是聲明三個指針變量。
(允許void類型的指針變量,void *p;//這樣的話指針就只是存放一個地址,并沒有說指針指向的是什么類型的)
變量a里面存放456,變量b里面存放的是不是c,而是c的ascii碼(字符在內(nèi)存中是以ASCII的形式存放的,告訴他是字符他就會把這個字符的ASCII值給讀取出來,然后去查ASCII表再把它給顯示出來)。
aPointer里面存放的是0(為什么不是0到3呢?因為只用知道他的初始地址,再用sizeof()知道它的長度就好了),因為aPointer存放的是a的地址,a變量的地址是從0到3,b變量的地址是從4到7,bPointer存放的是4。
如果*aPoint=123;將會變成
小Q問:
實現(xiàn)了通過指針對a改變值。
上述*p=5;//表示這里是對指針進行一個解引用,對指針進行賦值。
小O答:p?指向?a,你給?*p?賦值為?5,那么就是給?a?賦值為?5,a?的值當然會改變。p?不存儲真正的數(shù)值,a?才存儲數(shù)值,p?指向?a,所以?a?和?*p?的值永遠都是一致的,因為保存值的內(nèi)存只有一個。
小Q問:好,就是*p=5是給*p賦值并不是讓p指向了a?p的指向并沒有改變?還是a?
小O答:嗯,p?的指向沒有改變,這里的?*?表示取得指針指向的值,而不是表示指針。
小Q問:
,這句話的意思并不是強調(diào)指向,而是強調(diào)的是數(shù)據(jù)。那*p=5;這里是使用指針變量,表明的并不是p指向5?而是p仍然指向的是a。只是這個時候的變量a對應(yīng)的數(shù)據(jù)本身是5了,不是3?
小O答:是的。
如果你是沒有分配的或者不存在的,那么他保存的地址就是子虛烏有的。
? ? ?
---指針和數(shù)組
計算機把數(shù)組是以一組連續(xù)的內(nèi)存塊保存的。
數(shù)組擁有很多個地址,每個地址都擁有著一個元素,比如地址0、4、8等;而一個指針只能存放一個地址,數(shù)組的名字其實也是一個指針(指向數(shù)組的首地址,也就是第一個元素的地址)。
int *p1=&myArray[0];
int *p2=myArray;//這兩句是等價的。//實現(xiàn)了將數(shù)組的基地址用指針變量保存起來。
p1++//并不是將地址簡單的+1,而是按照指向的數(shù)組的數(shù)據(jù)類型來遞增的,也就是+sizeof(int);
#include<iostream>
using namespace std;
void print(int *pbegin,int *pend)
{while (pbegin != pend){cout << *pbegin;cout << '\n';++pbegin;}
}
void print(char *pbegin, char *pend)
{while (pbegin != pend){cout << *pbegin;cout << '\n';++pbegin;}
}
int main()
{int num[5] = { 0,1,2,3,4 };char name[5] = { 'f','i','s','h','c' };print(num, num + 5);cout << '\n';print(name, name + 5);cout << "\n";return 0;
}
把上邊重載函數(shù)改成用模板來簡化:
template <typename elemType> //模板的名字eleType
void print(elemType *pbegin, elemType *pend)
{while (pbegin != pend){cout << *pbegin;cout << '\n';++pbegin;}
}
-----對象的基礎(chǔ)-->結(jié)構(gòu)
結(jié)構(gòu)是由其他變量類型組合而成的數(shù)據(jù)類型。
指針也可以指向結(jié)構(gòu),就像指向其他變量那樣。
怎么通過指針解引用該指向結(jié)構(gòu)的各個成員(即通過指針訪問各個成員的值)。
數(shù)組的話是指針指向了他的一個基礎(chǔ)元素,然后后面的通過加上了指針的類型,直接將指針加1就是指向了下一個元素。
結(jié)構(gòu)跟數(shù)組差不多,指針指向的也是第一個成員的位置,如果訪問下一個只需要將指針加上第一個(前面的幾個)成員的寬度就好了(注意不是加1或者減1,因為結(jié)構(gòu)里邊的數(shù)據(jù)類型不同)。
//定義一個結(jié)構(gòu)
struct FishOil
{std::string name;std::string id;char sex;
};
//創(chuàng)建一個FishOil的結(jié)構(gòu)變量
FishOil jiayu={"小甲魚","fishc",'M'};
//創(chuàng)建一個指向該結(jié)構(gòu)的指針
FishOil *pjiayu=&jiayu;//此處的jiayu是一個結(jié)構(gòu)類型的變量//指針的類型必須與指向的地址的變量的類型一致,所以pjiayu指針的類型也是FishOil。
//我們可以通過對指針進行解引用來訪問相應(yīng)的變量值
(*pjiayu).name="白天";//改名字//因為*pjiayu就是相當于這個結(jié)構(gòu)變量 jiayu
也可以換用第二種方法進行訪問:
pjiayu->name="白天";//指針的話可以用箭頭的
pjiayu->id="0001234";
pjiayu->sex='F';
cout<<pjiayu->name;
cout<<pjiayu->id;
cout<<pjiayu->sex;
聯(lián)合類型
union mima
{unsigned long birthday;unsigned short ssn;char *get;
};//定義聯(lián)合體
mima mima1;//創(chuàng)建變量
枚舉類型
enum weekday{M,T,W,T,F};//定義枚舉類型
weekdays today;//創(chuàng)建該類型的變量
today=T;//對其進行賦值(賦值只能是賦上邊的5個中的一個)
typedef類型(定義類型別名)
//typedef用來替換類型別名
typedef int* intpointer;
intpointer mypointer;//intpointer就相當于int*;
向量類型(vector)類型---(是數(shù)組和鏈表的結(jié)合體)
?
?
?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的C++:随笔3--复杂的数据结构的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深度学习在图像领域的几大任务
- 下一篇: C++:随笔4--对象