C++遠征計劃的學習者確定是衝着封裝,繼承,多態來的。ios
知識點:c++
#define VS const(更強數據控制力)
引用類型:程序員
引用就是變量的別名數組
只有別名,別名就變成了真實姓名.只有別名也是沒法進行命名的。
#include <stdlib.h> #include <iostream> using namespace std; int main(void) { int a = 3; // 給a起了一個別名b int &b = a; //引用必須初始化 b = 10; // 給b賦值10,a的值也就由3變爲10 cout << a << endl; system("pause"); return 0; }
爲a起別名b: 對別名作的操做就是對a自己作了操做[叫小蘿蔔頭幹什麼,羅某某也幹了什麼]
使用別名對於結構體作操做的例子:函數
typedef struct { int x; int y; }Coor;
#include <stdlib.h> #include <iostream> using namespace std; typedef struct { int x; int y; }Coor; int main(void) { Coor c1; Coor &c = c1; // 給c1起了別名c c.x = 10; // 使用別名對真實值作操做 c.y = 20; cout << c1.x << endl << c1.y << endl; system("pause"); return 0; }
類型 *&指針引用名 = 指針;
#include <iostream> using namespace std; int main(void) { int a = 10; int *p = &a; // 定義指針p int *&q = p; // 指針p的別名q *q = 20; cout << a << endl; system("pause"); return 0; }
int a = 10;
// 給a分配一個內存邏輯地址,如0x100001。這個地址存放了值10;int *p = &a;
//建立指針變量p指向a,給p分配地址0x100002,這個地址存放的值是"0x100001"(a的邏輯地址值);-int *&q = p;
// (給指針p起別名q)建立變量q,給q分配地址也是0x100002, 所以這個地址存放的值仍是a的邏輯地址值;學習
*q = 20;
// (對q作操做)訪問存放在q變量地址下的值,得到了a的地址值, 再訪問一下a的地址值,修改裏面存放的內容爲20;C語言中將兩個數的值進行交換:spa
void fun(int *a, int *b) { int c =0; c =*a; *a =*b; *b =c; } int main() { int x =10; int y =20; fun(&x,&y); return 0; }
c++中引用實現:操作系統
void fun(int &a, int &b) { int c =0; c =a; a =b; b =c; } int main() { int x=10,y=20; fun(x,y) return 0; }
a是x的別名。b是y的別名。 裏面操做的就是實際的參數了。指針
基本數據類型引用示例:code
2-2-C++Two-ReferenceDemo/main.cpp
#include <iostream> #include <stdlib.h> using namespace std; int main(void) { int a = 10; int &b = a; // 定義一個引用(別名) // int &b = NULL; 計算機會報錯, 初始化 沒法從 int 轉換爲 int & b = 20; cout << a << endl; a = 30; cout << b << endl; system("pause"); return 0; }
對於本體和別名的操做具備相同的效果。
結構體引用示例:
2-2-2-C++Two-ReferenceStructDemo/main.cpp
#include <stdlib.h> #include <iostream> using namespace std; typedef struct { int x; int y; }Coord; //Coord 座標 int main(void) { Coord c; Coord &c1 = c; // 起別名c1 c1.x = 10; c1.y = 20; cout << c.x << endl << c.y << endl; system("pause"); return 0; }
指針引用示例:
2-2-3-C++Two-ReferencePointerDemo/main.cpp
#include <stdlib.h> #include <iostream> using namespace std; int main(void) { int a = 3; int *p = &a; int *&q = p; // 指針p的別名q *q = 5; cout << a << endl; system("pause"); return 0; }
函數參數引用示例:
2-2-4-C++Two-ReferenceFunctionParameter/main.cpp
#include <stdlib.h> #include <iostream> using namespace std; void fun(int &a, int &b); int main(void) { int x = 10; int y = 20; cout << x << endl; cout << y << endl; fun(x, y); cout << "交換後:" << endl; cout << x << endl; cout << y << endl; system("pause"); return 0; } void fun(int &a, int &b) { int c = 0; c = a; a = b; b = c; }
看起來傳入的是實參x,y 實際上 a是x的引用,b是y的引用
int a; int &b = a; int &c = a;
一個本體能夠起多個別名
定義一個引用y,y是x的引用,而後打印x和y的值。將y的值更改以後再次打印,x和y的值。
2-2-5-C++Two-ReferenceUnitDemo/main.cpp
#include <stdlib.h> #include <iostream> using namespace std; int main(void) { int x = 3; //定義引用,y是x的引用 int &y = x; //打印x和y的值 cout << x << endl; cout << y << endl; //修改y的值 y = 5; //再次打印x和y的值 cout << "After Change Y:" << endl; cout << x << "," << y << endl; system("pause"); return 0; }
const關鍵字是用來控制變量是否能夠變化的。
沒有const以前的狀況:
int x =3; //變量
const int x=3; //此時的x爲常量
x變成了一個常量,沒法進行更改。再賦值其餘數字,編譯時就會報錯。
const int *p=NULL;
徹底等價於int const *p=NULL
int *const p=NULL
與前兩種有區別。
const int * const p = NULL;
徹底等價於 int const * const p = NULL;
int x =3; const int *p = &x; // p = &y;正確 // *p = 4;錯誤
const 修飾*p
; 所以p能夠指向其餘的地址,但*P
不能夠被改變。
變量名 | 存儲地址 | 存儲內容 |
---|---|---|
x | &x | 3 |
p | &p | &x |
int x =3; int *const p = &x; // p = &y;錯誤 // *p = 4;正確
const寫在了
*
的後面。const 修飾p; const修飾的p只能指向一個地址。
變量名 | 存儲地址 | 存儲內容 |
---|---|---|
x | &x | 3 |
p | &p | &x (不可改變) |
const 修飾p;
const int x =3; const int *const p = &x; // p = &y; 錯誤 // *p = 4; 錯誤
變量名 | 存儲地址 | 存儲內容 |
---|---|---|
x | &x | 3 (不可改變) |
p | &p | &x (不可改變) |
int x =3; const int &y =x; // x=10; 正確 // y=20; 錯誤 y做爲別名加了const
變量名 | 存儲地址 | 存儲內容 |
---|---|---|
x | &x | 3 |
//錯誤 const int x =3; x =5; // 常量x不能進行賦值了 //錯誤 int x =3; const int y =x ; y = 5; // y 變成了常量,不能再賦值 //錯誤 int x =3; const int *y =&x; // 修飾*y *y = 5; // *y不可變化 //錯誤 int x =3,z=4; int * const y = &x; y = &z; // 修飾y 不容許從新指向 //錯誤 const int x =3; const int &y =x; y =5; //錯誤:指針會存在改變常量的風險。 const int x =3; int *y = &x; // x不可變,指針可變。 // 使用一個可變的指針,指向一個不可變的變量。風險是能夠經過*y的方式改變x的值。 // 編譯器會禁止 //正確。x擁有讀寫,y只可讀。 int x =3; const int *y =&x; //權限小的接收權限大的
3-2-1-constIntChangeDemo/main.cpp
#include "stdafx.h" #include <iostream> using namespace std; int main(void) { const int x = 3; x = 5; system("pause"); return 0; }
1> error C3892: 「x」: 不能給常量賦值
經過define和const修飾的均可以達成設置常量目的。
3-2-2-constPointerChangeDemo/main.cpp
#include <iostream> using namespace std; int main(void) { int x = 3; int y = 4; int const *p = &x; // const int *p = &x等價 // 都是修飾*p的 //*p = 5; x = 5; p = &y; cout << *p << endl; system("pause"); return 0; }
此時*p
的值不能進行修改。可是能夠修改p指針指向的地址
錯誤 C3892 「p」: 不能給常量賦值
3-2-3-constPointerChangeDemo2/main.cpp
#include <iostream> using namespace std; int main(void) { int x = 3; int y = 5; int *const p = &x; // const修飾p // p = &y; // p不能給常量賦值 *p = 10; cout << x << endl; system("pause"); return 0; }
此時對於p指向的地址不能修改。可是對於
*p
的值能夠進行修改。
3-2-4-constPointerMoveDemo/main.cpp
#include <iostream> using namespace std; int main(void) { int x = 3; int y = 5; int const *p = &x; cout << *p << endl; p = &y; //*p = 10; cout << *p << endl; system("pause"); return 0; }
由於此時const修飾的*p
,而p是能夠移動到其餘地址。
const修飾一個引用:
3-2-5-constReferenceDemo/main.cpp
#include <iostream> using namespace std; int main(void) { int x = 3; int y = 5; int const &z = x; // z = 10; // z不能被改變 x = 20; cout << x << endl; system("pause"); return 0; }
別名被限制上了不能修改,可是原變量是能夠修改的。
函數中的const
由於能夠保證傳入函數內部的值不會由於誤操做而修改原有值
3-2-6-constFunctionDemo/main.cpp
#include <iostream> using namespace std; void fun( const int &a, const int &b); int main(void) { int x = 3; int y = 5; fun(x, y); cout << x << "," << y << endl; system("pause"); return 0; } void fun( const int & a, const int & b) { // 錯誤由於傳入的值爲const。不能進行修改。 a = 10; b = 20; }
把const去掉,由於傳入的是引用,因此原始值能夠被修改。
而當const修飾以後,傳入函數內部的值並不會修改原有值
關於const用法,如下錯誤的是:
A. int const a = 3; int *p = &a; // B. int a = 3; int const *p = &a; C. int a = 3; int * const p = &a; D. const int a = 3; int const &b = a;
B const 修飾*p
C const 修飾p
D const修飾a的別名b
mtianyan:指針指向const修飾的變量時,應該是const int const *p = &a;
使用const關鍵字定義整型變量count,並定義指針p引用變量count。利用for循環打印count次Hello C++
3-4-C++-UnitDemo/main.cpp
#include <stdlib.h> #include <iostream> using namespace std; int main(void) { // 定義常量count const int count = 3; int const *p = &count; // 打印count次字符串Hello C++ for (int i = 0; i < *p; i++) { cout << "Hello C++" << endl; } system("pause"); return 0; }
由於只對*p
進行了const。所以可讓p指向其餘地址。
void fun(int i, int j=5, int k=10); // j,k有默認值 void fun(int i, int j=6, int k); // 錯誤寫法
有默認參數值的參數必須在參數表的最右端
聲明寫默認值,定義不建議寫。 定義時寫默認值有些編譯器沒法經過。
void fun(int i, int j = 5, int k = 10); void fun(int i, int j, int k) { cout << i << j << k; }
使用時:
int main() { fun(20); fun(20,30); fun(20,30,40); }
無實參則用默認值,不然實參覆蓋默認值
前提: 在相同做用域下
兩個條件:
demo代碼:
int getMax(int x, int y, int z) { //TO DO } double getMax(double x ,double y) { //TO DO }
思考:編譯器如何識別重載的函數
實際的編譯以後,名稱+參數造成新的函數。來區分兩個所謂的同名函數。
int getMax(int x, int y, int z)
->getMax_int_int_int
double getMax(double x ,double y)
->getMax_double_double
調用時,則根據實參類型和個數自動識別。
重載的好處:
![內聯函數](http://upload-images.jianshu....
strip%7CimageView2/2/w/1240)
主調函數調用普通函數有五個步驟:
- 調用fun(),2. 找到fun()的相關函數入口 3. 執行fun() 中的相關代碼 4. 返回主調函數
內聯函數會在編譯時將函數體代碼和實參代替函數調用語句。
內聯函數關鍵字inline
inline int max(int a,int b,int c); int main() { int i =10,j=20,k=30,m; m = max(i,j,k); cout<<"max="<<m<<endl; return 0; }
使用時和普通函數同樣使用。代碼展開後至關於代碼粘貼進來。
思考: 爲何不全部地方都使用內聯函數?
學習函數默認參數,重載,內聯函數。
4-2-c++-functionDefaultParameter/main.cpp
#include <stdlib.h> #include <iostream> using namespace std; void fun(int i=30, int j = 20, int k = 10); int main(void) { fun(); fun(100); fun(100, 200); fun(100, 200, 300); system("pause"); return 0; } void fun(int i, int j, int k) { cout << i << "," << j << "," << k << endl; }
已傳入的實參覆蓋默認值,未傳入的使用默認值。 默認值從右側開始賦值,聲明時賦默認值,定義時不要默認值。
前提條件,函數在同一個做用域下,默認多個函數在同一個命名空間時。
當沒有定義命名空間時,函數同名就默認是重載了。
4-2-C++-FunctionOverload/main.cpp
#include <stdlib.h> #include <iostream> using namespace std; void fun(int i = 30, int j = 20, int k = 10); void fun(double i = 30.0, double j = 40.0); int main(void) { // fun(); //「fun」 : 對重載函數的調用不明確 // 有多個 重載函數 "fun" 實例與參數列表匹配 fun(1, 2); fun(1.1, 2.2); system("pause"); return 0; } void fun(int i, int j, int k) { cout << i << "," << j << "," << k << endl; } void fun(double i, double j) { cout << i << "," << j << endl; }
fun() 兩個函數均可以,所以編譯器懵了。
inline函數實現只須要加上inline關鍵字
inline void fun(int i = 30, int j = 20, int k = 10); inline void fun(double i = 30.0, double j = 40.0);
inline這種內聯,只是一種編譯方式,結果上沒有什麼不一樣。
C++的重載的兩個函數參數數量能夠相同也能夠不一樣, 當參數數量相同時,只須要對應參數類型不一樣即稱爲重載。
4-4-ReturnMaxDemo/main.cpp
#include <stdlib.h> #include <iostream> using namespace std; /** *函數功能:返回a和b的最大值 *a和b是兩個整數 */ int getMax(int a, int b) { return a > b ? a : b; } /** * 函數功能:返回數組中的最大值 * arr:整型數組 * count:數組長度 * 該函數是對上面函數的重載 */ int getMax(int arr[], int count) { //定義一個變量並獲取數組的第一個元素 int a = arr[0]; for (int i = 1; i < count; i++) { //比較變量與下一個元素的大小 if (a <arr[i]) { //若是數組中的元素比maxNum大,則獲取數組中的值 a = arr[i]; } } return a; } int main(void) { //定義int數組並初始化 int numArr[3] = { 3, 8, 6 }; //自動調用int getMax(int a, int b) cout << getMax(6, 4) << endl; //自動調用返回數組中最大值的函數返回數組中的最大值 cout << getMax(numArr, 3) << endl; system("pause"); return 0; }
什麼是內存管理?
思考:內存的本質是什麼?
內存的本質是一種資源,由操做系統掌控。
咱們能作什麼?
咱們能夠對內存進行申請和歸還操做,申請/歸還內存資源稱爲內存管理。
運算符: new
delete
int *p=new int;
delete p;
這是申請和釋放某一個內存
int *arr=new int[10]; // 申請塊內存 delete []arr; // 釋放快內存
內存操做注意事項
回憶: 申請和釋放內存的其餘方式
void *malloc(size_t size); // 使用申請內存函數 void free(void *menblock); // 使用釋放內存函數
new
delete
運算符配套使用不要混搭
int *p=new int [1000]; if(NULL==p) { //內存分配失敗 }
釋放內存注意:
int *p=new int [1000]; if(NULL==p) { //內存分配失敗 } delete []p; p = NULL; int *p=new int; if(NULL==p) { //內存分配失敗 } delete p; p = NULL;
不置爲空,它就會指向剛纔那塊內存。咱們若是再次使用delete,就會形成同一塊內存回收兩次。
計算機會出現異常。
使用new
申請內存,使用delete
釋放內存,配套使用。
申請內存須要判斷是否失敗。釋放內存要記得指針置空。
new和delete配套使用
5-2-NewDeleteMemoryManage/main.cpp
#include <stdlib.h> #include <iostream> using namespace std; int main(void) { //int *p = new int(20); //申請同時初始化 int *p = new int; if (NULL == p) { system("pause"); return 0; } *p = 20; cout << *p << endl; delete p; p = NULL; system("pause"); return 0; }
申請塊內存:
5-2-2-BlockMemoryManage/main.cpp
#include <stdlib.h> #include <iostream> using namespace std; int main(void) { int *p = new int[1000]; if (NULL == p) { system("pause"); return 0; } p[0] = 10; p[1] = 20; cout << p[0] << "," << p[1] << endl; delete []p; // 注意這裏的[],不然只會釋放第一塊。 p = NULL; system("pause"); return 0; }
在堆中申請100個char類型的內存,拷貝Hello C++字符串到分配的堆中的內存中,打印字符串,最後釋放內存。
5-4-StrcpyMemoryMange/main.cpp
#include <string.h> #include <iostream> using namespace std; int main(void) { //在堆中申請100個char類型的內存 char *str = new char[100]; if (NULL == str) { system("pause"); return 0; } //拷貝Hello C++字符串到分配的堆中的內存中 strcpy_s(str,100,"Hello C++"); //打印字符串 cout << str << endl; //釋放內存 delete[]str; str = NULL; system("pause"); return 0; }
沒有與參數列表匹配的 重載函數 "strcpy_s",添加char數組的長度。