C/C++ 的一些亂七八糟的總結(一)

來源:互聯網
上載者:User

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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.