c++ 智能指針、函數指針和指針函數


智能指針:

1、內存泄漏memory leak :是指程序在申請內存后,無法釋放已申請的內存空間,一次內存泄漏似乎不會有大的影響,但內存泄漏堆積后的后果就是內存溢出
2、內存溢出 out of memory :指程序申請內存時,沒有足夠的內存供申請者使用,或者說,給了你一塊存儲int類型數據的存儲空間,但是你卻存儲long類型的數據,那么結果就是內存不夠用,此時就會報錯OOM,即所謂的內存溢出。

 

智能指針和普通指針的區別在於智能指針實際上是對普通指針加了一層封裝機制,區別是它負責自動釋放所指的對象,這樣的一層封裝機制的目的是為了使得智能指針可以方便的管理一個對象的生命期。

智能指針的原理:智能指針是一個類,這個類的構造函數中傳入一個普通指針,析構函數中釋放傳入的指針。智能指針的類是棧上的對象,智能指針指向堆上開辟的空間,函數結束時,棧上的函數會自動被釋放,智能指針指向的內存也會隨之消失,防止內存泄漏。

shared_ptr 是一個標准的共享所有權的智能指針, 允許多個指針指向同一個對象. 定義在 memory 文件中(非memory.h), 命名空間為 std,可以拷貝和賦值

shared_ptr就是為了解決auto_ptr在對象所有權上的局限性,在使用引用計數的基礎上提供了可以共享所有權的智能指針

 

在C++中,我們知道,如果使用普通指針來創建一個指向某個對象的指針,那么在使用完這個對象之后我們需要自己刪除它,例如:

ObjectType* temp_ptr = new ObjectType();
temp_ptr->foo();
delete temp_ptr;

很多材料上都會指出說如果程序員忘記在調用完temp_ptr之后刪除temp_ptr,那么會造成一個懸掛指針(dangling pointer),也就是說這個指針現在指向的內存區域其內容程序員無法把握和控制,也可能非常容易造成內存泄漏。可是事實上,不止是“忘記”,在上述的這一段程序中,如果foo()在運行時拋出異常,那么temp_ptr所指向的對象仍然不會被安全刪除。在這個時候,智能指針的出現實際上就是為了可以方便的控制對象的生命期,在智能指針中,一個對象什么時候和在什么條件下要被析構或者是刪除是受智能指針本身決定的,用戶並不需要管理。

shared_ptr: shared_ptr中所實現的本質是引用計數(reference counting),也就是說shared_ptr是支持復制的,復制一個shared_ptr的本質是對這個智能指針的引用次數加1,而當這個智能指針的引用次數降低到0的時候,該對象自動被析構

需要特別指出的是,如果shared_ptr所表征的引用關系中出現一個環,那么環上所述對象的引用次數都肯定不可能減為0那么也就不會被刪除,為了解決這個問題引入了weak_ptr。

 

智能指針最基本的概念是引用計數,也就是智能指針內部有一個計數器,記錄了當前內存資源到底有多少指針在引用(可以訪問這個資源),當新增加一個可以訪問這個資源的引用時,計數器會加1,反之會減去1,並且用一個操作對象和內存的關系,當計數器為0時,智能指針會自動釋放他所管理的資源。手動申請,自動釋放,就是其智能的體現。

例如:
int main()
{

  { // 局部作用域

    shared_ptr<int> p(new int);// 引用計數:1,也就是只有一個指針p引用(訪問)這塊int內存

  {

    shared_ptr<int> copy = p;// 引用計數:2,指針p和copy兩個指針可以訪問這塊內存

  }

  // 引用計數:1,超出copy的作用域,只有p可以訪問這塊內存

  } // 引用計數:0,超出p的作用域,沒有指針可以訪問這塊內存, 資源被自動釋放

  return 0;

}

 
 
指針函數:一個函數,它的返回值是指針
函數指針:指向函數的指針
作用:在運行時根據數據的具體狀態來選擇相應的處理方式
例子:
函數指針是需要把一個函數的地址賦值給它,有兩種寫法:
fun = &Function;
fun = Function;

調用函數指針的方式也有兩種:

x = (*fun)();
x = fun();

 

int add(int x,int y){
    return x+y;
}
int sub(int x,int y){
    return x-y;
}
//函數指針
int (*fun)(int x,int y);

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //第一種寫法
    fun = add;
    qDebug() << "(*fun)(1,2) = " << (*fun)(1,2) ;
    //第二種寫法
    fun = &sub;
    qDebug() << "(*fun)(5,2) = " << (*fun)(5,3)  << fun(5,3);

    return a.exec();
}

輸出:

(*fun)(1,2) = 3

(*fun)(5,2) = 2 2


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM