最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于C++內(nèi)存分配、函數(shù)調(diào)用與返回值的深入分析

 更新時間:2013年05月28日 16:59:33   作者:  
本篇文章是對C++中的內(nèi)存分配、函數(shù)調(diào)用與返回值進行了詳細的分析介紹,需要的朋友參考下
在談述函數(shù)調(diào)用和返回值問題之前,先來看看C++中內(nèi)存分配的問題。
C++編譯器將計算機內(nèi)存分為代碼區(qū)和數(shù)據(jù)區(qū),很顯然,代碼區(qū)就是存放程序代碼,而數(shù)據(jù)區(qū)則是存放程序編譯和執(zhí)行過程出現(xiàn)的變量和常量。數(shù)據(jù)區(qū)又分為靜態(tài)數(shù)據(jù)區(qū)、動態(tài)數(shù)據(jù)區(qū),動態(tài)數(shù)據(jù)區(qū)包括堆區(qū)和棧區(qū)。
以下是各個區(qū)的作用:
(1)代碼區(qū):存放程序代碼;
(2)數(shù)據(jù)區(qū)
a.靜態(tài)數(shù)據(jù)區(qū): 在編譯器進行編譯的時候就為該變量分配的內(nèi)存,存放在這個區(qū)的數(shù)據(jù)在程序全部執(zhí)行結(jié)束后系統(tǒng)自動釋放,生命周期貫穿于整個程序執(zhí)行過程。
b.動態(tài)數(shù)據(jù)區(qū):包括堆區(qū)和棧區(qū)
堆區(qū):這部分存儲空間完全由程序員自己負責管理,它的分配和釋放都由程序員自己負責。這個區(qū)是唯一一個可以由程序員自己決定變量生存期的區(qū)間??梢杂胢alloc,new申請對內(nèi)存,并通過free和delete釋放空間。如果程序員自己在堆區(qū)申請了空間,又忘記將這片內(nèi)存釋放掉,就會造成內(nèi)存泄露的問題,導(dǎo)致后面一直無法訪問這片存儲區(qū)域。
棧區(qū):存放函數(shù)的形式參數(shù)和局部變量,由編譯器分配和自動釋放,函數(shù)執(zhí)行完后,局部變量和形參占用的空間會自動被釋放。效率比較高,但是分配的容量很有限。
注意:
1)全局變量以及靜態(tài)變量存放在靜態(tài)數(shù)據(jù)區(qū);
2)注意常量的存放區(qū)域,通常情況下,常量存放在程序區(qū)(程序區(qū)是只讀的,因此任何修改常量的行為都是非法的),而不是數(shù)據(jù)區(qū)。有的系統(tǒng),也將部分常量分配到靜態(tài)數(shù)據(jù)區(qū),比如字符串常量(有的系統(tǒng)也將其分配在程序區(qū))。但是要記住一點,常量所在的內(nèi)存空間都是受系統(tǒng)保護的,不能修改。對常量空間的修改將造成訪問內(nèi)存出錯,一般系統(tǒng)都會提示。常量的生命周期一直到程序執(zhí)行結(jié)束為止。
在弄懂內(nèi)存分配的問題過后,來看看函數(shù)調(diào)用的過程:
執(zhí)行某個函數(shù)時,如果有參數(shù),則在棧上為形式參數(shù)分配空間(如果是引用類型的參數(shù)則類外),繼續(xù)進入到函數(shù)體內(nèi)部,如果遇到變量,則按情況為變量在不同的存儲區(qū)域分配空間(如果是static類型的變量,則是在進行編譯的過程中已經(jīng)就分配了空間),函數(shù)內(nèi)的語句執(zhí)行完后,如果函數(shù)沒有返回值,則直接返回調(diào)用該函數(shù)的地方(即執(zhí)行遠點),如果存在返回值,則先將返回值進行拷貝傳回,再返回執(zhí)行遠點,函數(shù)全部執(zhí)行完畢后,進行退棧操作,將剛才函數(shù)內(nèi)部在棧上申請的內(nèi)存空間釋放掉。
下面通過幾個例子來談?wù)?FONT style="COLOR: #ff0000">內(nèi)存分配和函數(shù)返回值的問題:
內(nèi)存分配的問題:
復(fù)制代碼 代碼如下:

int a=1;           a在棧區(qū)
char s[]="123";    s在棧區(qū),“123”在棧區(qū),其值可以被修改
char *s="123";     s在棧區(qū),“123”在常量區(qū),其值不能被修改
int *p=new int;    p在棧區(qū),申請的空間在堆區(qū)(p指向的區(qū)域)
int *p=(int *)malloc(sizeof(int)); p在棧區(qū),p指向的空間在堆區(qū)
static int b=0;    b在靜態(tài)區(qū)

1.test1 
復(fù)制代碼 代碼如下:

#include<iostream>
using namespace std;
void test(int *p)
{
    int b=2;
    p=&b;
    cout<<p<<endl;
}
int main(void)
{
    int a=10;
    int *p=&a;
    cout<<p<<endl;
    test(p);
    cout<<p<<endl;
    return 0;
}

第一行輸出和第三行輸出的結(jié)果相同,而第一行、第三行與第二行輸出的結(jié)果不同。從這里可以看出,當指針作為參數(shù)進行傳遞時傳遞的也只是一個值,只不過該值只一個地址,因此對于形參的改變并不影響實參。
2.test2
復(fù)制代碼 代碼如下:

#include<iostream>
using namespace std;
char* test(void)
{
    char str[]="hello world!";
    return str;
}
int main(void)
{
    char *p;
    p=test();
    cout<<p<<endl;
    return 0;
}

輸出結(jié)果可能是hello world!,也可能是亂麻。
出現(xiàn)這種情況的原因在于:在test函數(shù)內(nèi)部聲明的str數(shù)組以及它的值"hello world”是在棧上保存的,當用return將str的值返回時,將str的值拷貝一份傳回,當test函數(shù)執(zhí)行結(jié)束后,會自動釋放棧上的空間,即存放hello world的單元可能被重新寫入數(shù)據(jù),因此雖然main函數(shù)中的指針p是指向存放hello world的單元,但是無法保證test函數(shù)執(zhí)行完后該存儲單元里面存放的還是hello world,所以打印出的結(jié)果有時候是hello world,有時候是亂麻。
3.test3 
復(fù)制代碼 代碼如下:

#include<iostream>
using namespace std;
int test(void)
{
    int a=1;
    return a;
}
int main(void)
{
    int b;
    b=test();
    cout<<b<<endl;
    return 0;
}

輸出結(jié)果為 1
有人會問為什么這里傳回來的值可以正確打印出來,不是棧會被刷新內(nèi)容么?是的,確實,在test函數(shù)執(zhí)行完后,存放a值的單元是可能會被重寫,但是在函數(shù)執(zhí)行return時,會創(chuàng)建一個int型的零時變量,將a的值復(fù)制拷貝給該零時變量,因此返回后能夠得到正確的值,即使存放a值的單元被重寫數(shù)據(jù),但是不會受到影響。
4.test4
復(fù)制代碼 代碼如下:

#include<iostream>
using namespace std;
char* test(void)
{
    char *p="hello world!";
    return p;
}
int main(void)
{
    char *str;
    str=test();
    cout<<str<<endl;
    return 0;
}

執(zhí)行結(jié)果是 hello world!
同樣返回的是指針,為什么這里會正確地打印出hello world1?這是因為char *p="hello world!",指針p是存放在棧上的,但是"hello world!”是一個常量字符串,因此存放在常量區(qū),而常量區(qū)的變量的生存期與整個程序執(zhí)行的生命期是一樣的,因此在test函數(shù)執(zhí)行完后,str指向存放“hello world!”的單元,并且該單元里的內(nèi)容在程序沒有執(zhí)行完是不會被修改的,因此可以正確輸出結(jié)果。
5.test5
復(fù)制代碼 代碼如下:

#include<iostream>
using namespace std;
char* test(void)
{
    char *p=(char *)malloc(sizeof(char)*100);
    strcpy(p,"hello world");
    return p;
}
int main(void)
{
    char *str;
    str=test();
    cout<<str<<endl;
    return 0;
}

運行結(jié)果 hello world
這種情況下同樣可以輸出正確的結(jié)果,是因為是用malloc在堆上申請的空間,這部分空間是由程序員自己管理的,如果程序員沒有手動釋放堆區(qū)的空間,那么存儲單元里的內(nèi)容是不會被重寫的,因此可以正確輸出結(jié)果。
6.test6
復(fù)制代碼 代碼如下:

#include<iostream>
using namespace std;
void test(void)
{
    char *p=(char *)malloc(sizeof(char)*100);
    strcpy(p,"hello world");
    free(p);
    if(p==NULL)
    {
        cout<<"NULL"<<endl;
    }
}
int main(void)
{
    test();
    return 0;
}

沒有輸出
在這里注意了,free()釋放的是指針指向的內(nèi)存!注意!釋放的是內(nèi)存,不是指針!這點非常非常重 要!指針是一個變量,只有程序結(jié)束時才被銷毀。釋放了內(nèi)存空間后,原來指向這塊空間的指針還是存在!只不過現(xiàn)在指針指向的內(nèi)容的垃圾,是未定義的,所以說是垃圾。因此,釋放內(nèi)存后應(yīng)把把指針指向NULL,防止指針在后面不小心又被使用,造成無法估計的后果。

相關(guān)文章

  • C語言順序查找算法介紹及示例

    C語言順序查找算法介紹及示例

    順序查找又稱線性查找,主要用于在線性表中進行查找。順序查找通常分為對一般的無序線性表的順序查找和對按關(guān)鍵字有序的順序表的順序查找,下面我們來一探究竟
    2022-08-08
  • C++實現(xiàn)LeetCode(132.拆分回文串之二)

    C++實現(xiàn)LeetCode(132.拆分回文串之二)

    這篇文章主要介紹了C++實現(xiàn)LeetCode(132.拆分回文串之二),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • 基于QT5實現(xiàn)一個時鐘桌面

    基于QT5實現(xiàn)一個時鐘桌面

    這篇文章主要介紹了利用QT5實現(xiàn)的一個時鐘桌面,文中的示例代碼講解詳細,對我們學(xué)習(xí)或工作有一定的幫助,感興趣的小伙伴可以了解一下
    2022-01-01
  • C/C++ 數(shù)組和指針及引用的區(qū)別

    C/C++ 數(shù)組和指針及引用的區(qū)別

    這篇文章主要介紹了C/C++ 數(shù)組和指針及引用的區(qū)別的相關(guān)資料,這里從匯編的角度來分析他們之間的區(qū)別,需要的朋友可以參考下
    2017-07-07
  • C++實現(xiàn)簡單推箱子小游戲

    C++實現(xiàn)簡單推箱子小游戲

    這篇文章主要為大家詳細介紹了C++實現(xiàn)簡單推箱子小游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-08-08
  • C?與?C++?中的?const?常量與數(shù)組大小的關(guān)系對比分析

    C?與?C++?中的?const?常量與數(shù)組大小的關(guān)系對比分析

    C和C++中數(shù)組大小通常要求是一個編譯時常量,C語言中,const變量不能直接作為數(shù)組大小,需要使用#define或enum,C++中,const變量被視為常量表達式,可以作為數(shù)組大小,本文介紹C?與?C++?中的?const?常量與數(shù)組大小的關(guān)系,感興趣的朋友一起看看吧
    2025-02-02
  • C/C++獲取主機網(wǎng)卡MAC地址的三方法

    C/C++獲取主機網(wǎng)卡MAC地址的三方法

    MAC地址(Media Access Control address),又稱為物理地址或硬件地址,是網(wǎng)絡(luò)適配器(網(wǎng)卡)在制造時被分配的全球唯一的48位地址,通過獲取MAC地址可以判斷當前主機的唯一性可以與IP地址綁定并實現(xiàn)網(wǎng)絡(luò)準入控制,本文給大家介紹了使用C/C++獲取主機網(wǎng)卡MAC地址的三方法
    2023-11-11
  • C++入門教程詳解之命名空間、函數(shù)重載、缺省參數(shù)

    C++入門教程詳解之命名空間、函數(shù)重載、缺省參數(shù)

    這篇文章主要介紹了C++入門教程詳解之命名空間、函數(shù)重載、缺省參數(shù),本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-06-06
  • C語言lseek()函數(shù)詳解

    C語言lseek()函數(shù)詳解

    這篇文章主要介紹了C語言lseek()函數(shù)詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • C++實現(xiàn)動態(tài)綁定代碼分享

    C++實現(xiàn)動態(tài)綁定代碼分享

    對于C++動態(tài)綁定的理解,就是編譯器用靜態(tài)分析的方法加上虛擬函數(shù)的設(shè)計實現(xiàn)在程序運行時動態(tài)智能執(zhí)行正確虛擬函數(shù)的技術(shù)。要徹底理解動態(tài)綁定,只需要掌握兩點,一是編譯器的靜態(tài)編譯過程,二是虛擬函數(shù)的基本知識。只要有了這兩點理解,任何動態(tài)綁定的分析都是很容易的
    2015-11-11

最新評論

江川县| 峨边| 顺平县| 遂平县| 云南省| 万荣县| 阳东县| 蓬溪县| 阳朔县| 龙陵县| 昌邑市| 沿河| 台江县| 浮山县| 承德市| 昔阳县| 顺昌县| 铜山县| 日土县| 陆河县| 大英县| 喀喇| 同心县| 卢龙县| 龙井市| 右玉县| 新龙县| 彩票| 舒城县| 青龙| 余庆县| 宁德市| 佛冈县| 九台市| 三亚市| 垣曲县| 新巴尔虎左旗| 平定县| 临清市| 蒲城县| 太仓市|