0.最近在複習C++,好多東西都忘了 ==!!
從部落格中,書中看到的一些東西,在這裡簡單總結下,沒有章法,看到哪,複習到哪
1. 引用
C++中引用 具備了 指標的 所有功能
區別:
(1) 引用在定義時必須初始化.引用和變數共用同一塊記憶體空間,而指標單專屬記憶體空間
(2) 指標進行刪除後,一般需要將其指向NULL,防止野指標,而引用至始而終都是它初始化時的地址,而且也不用刪除,它會在範圍範圍外由系統回收
引用和它引用的變數指向的是同一塊記憶體空間
當修改其中任意一個值時,兩個值都改變,當對引用重新賦一個新值時,引用的值和原來引用指向的值都改變為這個新值,而引用地址不變
在C ++ 中還可以定義一個類的對象的引用,與對象共用一塊記憶體
C++中 3 種傳遞函數參數的方式
(1)按值傳遞
(2)引用傳遞
(3)指標傳遞
3種方式的範例程式碼如下:
#include <iostream>using namespace std;void f(int a){ a = 10; cout << "函數f()中 a = " << a << endl;}void g(int * a){ *a = 15; cout << "函數g() 中 a = " << *a << endl;}void h(int &a){ a = 20; cout << "函數h() 中 a = " << a << endl;}int main(){ int a = 1; cout << "按值傳遞前 a = " << a << endl; f(a); cout << "按值傳遞後 a = " << a << endl; cout << "按地址傳遞前 a = " << a << endl; g(&a); cout << "按地址傳遞後 a = " << a << endl; cout << "按引用傳遞前 a = " << a << endl; h(a); cout << "按引用傳遞後 a = " << a << endl; return 0;}
可以看到按值傳遞,函數f()是不能修改a的
因為按值傳遞,只是把主函數a的值給了f函數的a值,這兩個a的地址不是同一個地址,
在執行的過程中,會把主函數a的地址的資料拷貝給set函數a的地址
2 c++ 記憶體管理
記憶體配置方式
1. 從靜態區分配,一般是全域變數和static類型變數
2.從棧區分配記憶體,一般是局部的變數,會隨著所在函數的結束而自動釋放
3.從堆中分配,一般是使用手動分配,使用malloc()函數和new來申請任意大小空間,不過要手動釋放空間,相應的使用free()函數和delete釋放,
如果不釋放該空間,而且指向該空間的指標指向了別的空間.則該空間就無法釋放,造成記憶體泄露,造成了記憶體浪費
動態記憶體釋放問題與野指標
當我們使用free()和delete釋放一塊記憶體時,指標還是指向原來的地址,不過這時候的指標時野指標
1.指標銷毀了,並不表示所指的空間也得到了釋放 :記憶體泄露
2.記憶體被釋放了,並不表示指標也被銷毀了或指向NULL :野指標
範例程式碼:
#include <iostream>#include <stdio.h>#include <stdlib.h>#include <string.h>using namespace std;int main(){ char *p = (char *)malloc(100); memset(p,0,10);//一般申請記憶體後,最好使用memset初始化一下 strcpy(p,"hello world!"); if(p) { cout << "p:" << p << endl; } free(p); // 所謂的野指標 cout << "p:" << p << endl; if(p != NULL) { cout << "p不為空白!" << endl; } p = NULL; return 0;}
指標的記憶體的傳遞
View Code
#include <iostream>
#include <stdlib.h>
#include <string.h>
using namespace std;
// 返回記憶體位址方式,這是正確的 !
//因為是動態記憶體分配,在堆上分配的
char * getMemory()
{
char *p = NULL;
p = (char *)malloc(sizeof(char));
memset(p,0,sizeof(char));
return p;
}
//常見錯誤是在棧上分配的被返回了,錯誤的
char *getMemory2()
{
char p [] = "hello world";
return p;
}
//通過指標的指標方式申請記憶體
void getMemory3(char ** p)
{
*p = NULL;
*p = (char *)malloc(sizeof(char));
if(*p)
{
cout << "p:" << p << endl;
}
}
int main()
{
char *p1 = NULL;
char *p2 = NULL;
char *p3 = NULL;
p1 = getMemory();
if(p1)
{
cout << "p1申請成功!" << endl;
}
p2 = getMemory2();
if(p2)
{
cout << "p2申請成功!" << endl;
cout << "p2:" << p2 << endl;
}
getMemory3(&p3);
if(p3)
{
cout << "p3申請成功!" << endl;
}
return 0;
}
3 動態數組(從csdn還是cnblogs中看到的,直接在這貼吧,網址找不到了)
1維
#include <stdio.h>#include <stdlib.h>int main(){int n1,i;int *array;printf("請輸入所要建立的一維動態數組的長度:");scanf("%d",&n1);array=(int*)calloc(n1,sizeof(int));for(i=0;i<n1;i++){ printf("%d\t",array[i]);}printf("\n");for(i=0;i<n1;i++){ array[i]=i+1; printf("%d\t",array[i]);} free(array);//釋放第一維指標return 0;}
2維
#include <stdio.h>#include <stdlib.h>int main(){int n1,n2;int **array,i,j;printf("請輸入所要建立的動態數組的第一維長度:");scanf("%d",&n1);printf("請輸入所要建立的動態數組的第二維長度:");scanf("%d",&n2);array=(int**)malloc(n1*sizeof(int*)); //第一維for(i=0;i<n1; i++){array[i]=(int*)malloc(n2* sizeof(int));//第二維}for(i=0;i<n1;i++){for(j=0;j<n2;j++){array[i][j]=i*n2+j+1;printf("%d\t",array[i][j]);}printf("\n");}for(i=0;i<n1;i++){free(array[i]);//釋放第二維指標}free(array);//釋放第一維指標return 0;}
3維
#include <stdlib.h>#include <stdio.h>int main(){int n1,n2,n3;int ***array;int i,j,k;printf("請輸入所要建立的動態數組的第一維長度:");scanf("%d",&n1);printf("請輸入所要建立的動態數組的第二維長度:");scanf("%d",&n2);printf("請輸入所要建立的動態數組的第三維長度:");scanf("%d",&n3);array=(int***)malloc(n1*sizeof(int**));//第一維for(i=0; i<n1; i++){array[i]=(int**)malloc(n2*sizeof(int*)); //第二維for(j=0;j<n2;j++){array[i][j]=(int*)malloc(n3*sizeof(int)); //第三維}}for(i=0;i<n1;i++){for(j=0;j<n2;j++){for(k=0;k<n3;k++){array[i][j][k]=i+j+k+1;printf("%d\t",array[i][j][k]);}printf("\n");}printf("\n");}for(i=0;i<n1;i++){for(j=0;j<n2;j++){free(array[i][j]);//釋放第三維指標}}for(i=0;i<n1;i++){free(array[i]);//釋放第二維指標}free(array);//釋放第一維指標return 0;}
更多的維度也能照此寫出來
使用recolloc進行數組的擴大或者縮小:
擴大
#include <stdio.h>#include <stdlib.h>int main(){int*n,*p;int i,n1,n2;printf("請輸入所要建立的動態數組的長度:");scanf("%d",&n1);n=(int*)calloc(n1,sizeof(int));printf("請輸入所要擴充的動態數組的長度:");scanf("%d",&n2);p=(int*)realloc(n,(n2)*sizeof(int));//動態擴充數組for(i=0;i<n2;i++){p[i]=i+1;if(i%5==0)printf("\n");printf("%d\t",p[i]);}free(p);return 0;}
縮小
#include <stdio.h>#include <stdlib.h>int main(){int*n,*p;int i,n1,n2;printf("請輸入所要建立的動態數組的長度:");scanf("%d",&n1);n=(int*)calloc(n1,sizeof(int));for(i=0;i<n1;i++){n[i]=i+1;if(i%5==0)printf("\n");printf("%d\t",n[i]);}printf("\n請輸入所要縮小的動態數組的長度:");scanf("%d",&n2);p=(int*)realloc(n,(n2)*sizeof(int));for(i=0;i<n2;i++){if(i%5==0)printf("\n");printf("%d\t",p[i]);}printf("\n");free(p);return 0;}
4. sizeof()
#include <iostream>#include <stdio.h>using namespace std; //linux核心鏈表裡的一個宏 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)4)->MEMBER)typedef struct stu1{ int a; int b;}stu1;void print(){ cout << "hello world" << endl;}int print2(){ cout << "hello world" << endl; return 1;}#pragma pack (1) /*指定按1位元組對齊*/typedef union stu{char str[10];int b;}stu;#pragma pack () /*取消指定對齊,恢複預設對齊*/typedef union stu2{char str[10];int b;}stu2;int main(){ int i; //sizeof可以對一個運算式求值,編譯器根據運算式的最終結果確定大小 //但是不會對錶達式進行計算,不會對函數進行執行printf("sizeof(i):\t%d\n",sizeof(i));printf("sizeof(4):\t%d\n",sizeof(4));printf("sizeof(4+2.5):\t%d\n",sizeof(4+2.5));printf("sizeof(int):\t%d\n",sizeof(int));printf("sizeof 5:\t%d\n",sizeof 5);cout << "============================" << endl; //對於void類型,其長度為1 cout << sizeof(print()) << endl;
//int型的傳回值,其長度為4(都是在32位機器)
cout << sizeof(print2()) << endl; cout << "============================" << endl; printf("offsetof(stu1,a):%d\n",offsetof(stu1,a)-4); cout << "ofsetof(stu1,a):" << offsetof(stu1,a) - 4 << endl; printf("offsetof(stu1,b):%d\n",offsetof(stu1,b)-4); cout << "============================" << endl; printf("sizeof(stu) :\t%d\n",sizeof(stu)); printf("sizeof(stu2) :\t%d\n",sizeof(stu2)); return 0;}
對於結構體:
#include <stdio.h>typedef struct stu1{char array[7];}stu1;typedef struct stu2{double fa;}stu2;typedef struct stu3{stu1 s;char str;}stu3;typedef struct stu4{stu2 s;char str;}stu4;typedef struct stu5{ double d1; int i1; char c1;}stu5;typedef union stu6{ double d1; int i1; char c1;}stu6;typedef struct stu7{ char c1; int i1; double d1;}stu7;typedef struct stu8{ int i1; char c1; double d1;}stu8;int main(){printf("sizeof(stu1) :\t%d\n",sizeof(stu1));printf("sizeof(stu2) :\t%d\n",sizeof(stu2));printf("sizeof(stu3) :\t%d\n",sizeof(stu3));printf("sizeof(stu4) :\t%d\n",sizeof(stu4));printf("sizeof(stu5) :\t%d\n",sizeof(stu5));printf("sizeof(stu6) :\t%d\n",sizeof(stu6));printf("sizeof(stu7) :\t%d\n",sizeof(stu7));printf("sizeof(stu8) :\t%d\n",sizeof(stu8));return 0;}
size_t ,對於大小的比較,或者其他計算,會變成其補碼形式
#include <iostream>using namespace std;int main(){ size_t a = -1; size_t b = 10; if(a<b) cout << "a < b" << endl; else cout << "a !< b" << endl; return 0;}
答案是 a !< b
5 一道堆棧指標問題
#include <iostream>using namespace std;//指標的地址是在棧中(首地址除外),但是指標指向的內容卻在堆中,//所以並沒有被清除char* get_str(){ char* str = {"abcd"}; return str;}//棧裡面的變數都是臨時的。當前函數執行完成時,//相關的臨時變數和參數都被清除了,所以返回的指標指向的已經是隨機的了//但是str[]首地址被當成指標來處理,存放在堆中。char* get_str2(){ char str[] = {"abcd"}; return str;}int main(int argc, char* argv[]){ char* p = get_str(); cout << *p << endl; cout << *(p+1) << endl; cout << p << endl; cout << "========================" << endl; char *p2 = get_str2(); //第1次執行 *p2的時候,由於p2指標的首地址被返回了,還是可以取到*p2的內容的 /* 可以試試取*(p2+1),也是可以取到的 */ cout << *p2 << endl; //第一次調用*p2的時候還是有資料的,但是第2次就沒有了, //說明cout之後指標已經被破壞了 cout << *p2 << endl; cout << *(p2+1) <<endl; cout << *p2 << endl; cout << p2 << endl; return 0;}
參考:整理自互連網
http://blog.csdn.net/bizhu12/article/details/6668834
http://blog.csdn.net/bizhu12/article/details/6666176
http://blog.csdn.net/bigloomy/article/category/840249