1. 程式人生 > >C++迴圈引用和仿函式的使用

C++迴圈引用和仿函式的使用

迴圈引用

#include <iostream>
#include <memory.h>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
using namespace std;

template<class T>
struct ListNode
{
    ListNode(const T& data)
        :_prev(NULL)
        ,_next(NULL)
        ,_data(data)
    {
        cout
<<"ListNode()"<<endl; } ~ListNode() { cout<<"~Node()"<<this<<endl; } shared_ptr<ListNode> _prev; shared_ptr<ListNode> _next; //weak_ptr<ListNode> _prev; //weak_ptr<ListNode> _next; T _data; }; void Test() { //迴圈引用問題
shared_ptr<ListNode> p1(new ListNode()); shared_ptr<ListNode> p2(new ListNode()); cout<<"p1->Count:"<<p1.use_count()<<endl; cout<<"p2->Count:"<<p2.use_count()<<endl; p1->_next = p2;//p1節點的_next指向p2節點 p2->_prev = p1;//p2節點的_prev指向p1節點
cout<<"p1->Count:"<<p1.use_count()<<endl; cout<<"p2->Count:"<<p2.use_count()<<endl; }

使用shared_ptr時,由於節點之間的相互引用使得多個節點指向同一塊空間,引用計數count不為1。在釋放空間時,p1等待p2釋放,而p2又在等待p1的釋放,從而引起迴圈引用問題,造成記憶體洩漏。

仿函式:也叫函式物件。就是使一個類的使用看上去像一個函式。其實現原理就是就是在類中過載(),這個類就有了類似函式的行為,同時也成為一個仿函式類了

下面兩個仿函式的使用例子

定製刪除器

#include <iostream>
using namespace std;

template<class T>
struct Delete
{
    void operator ()(T* p)
    {
        delete(p);
        cout<<"Delete"<<endl;
    }
};

template<class T>
struct Free
{
    void operator ()(T* p)
    {
        free(p);
        cout<<"Free"<<endl;
    }
};

template<class T>
struct Fclose
{
    void operator ()(T* p)
    {
        fclose(p);
        cout<<"Fclose"<<endl;
    }
};

template<class T, class Del = Del<T>>
class SharedPtr
{
public:
    SharedPtr(T* p =NULL)
        :_p(p)
        ,_pcount(NULL)
    {
        if(_p)
            _pcount = new int(1);
    }

    SharedPtr(const SharedPtr<T, Del>& sp)
        :_p(sp._p)
        ,_pcount(sp._pcount)
    {
        (*sp._pcount)++;
    }

    SharedPtr<T, Del>& operator =(const SharedPtr<T, Del>& sp)
    {
        if(this != &sp)
        {
            Release();

            _p = sp._p;
            _pcount = sp._pcount;
            (*sp._pcount)++;
        }
        return *this;
    }

    ~SharedPtr()
    {
        Release();
    }

    T& operator *()
    {
        return *_p;
    }

    T* operator ->()
    {
        return _p;
    }
private:
    void Release()
    {
        if(_p && (--(*_pcount)) == 0)
        {
            Del()(_p);

            delete _pcount;
            _pcount = NULL;
        }
    }

    T* _p;
    int* _pcount;
};

int main()
{
    SharedPtr<int, Free<int>> sp1((int*)malloc(sizeof(int)));
    SharedPtr<int, Delete<int>> sp2(new int(1));
    SharedPtr<FILE, Fclose<FILE>> sp3(fopen("test.txt", "wb"));
}

這裡寫圖片描述

多重氣泡排序

#include <iostream>
using namespace std;

template<class T>
struct Great//升序
{
    bool operator ()(T& left, T& right)
    {
        return left > right;
    }
};

template<class T>
struct Less//降序
{
    bool operator ()(T& left, T& right)
    {
        return left > right;
    }
};

template<class T, class Compare>
void BubbleSort(T arr[], int len)
{
    int i = 0;
    int j = 0;
    int flag = 0;

    for(i = 0; i < len-1; i++)
    {
        flag = 0;
        for(j = 0; j < len-1-i; j++)
        {
            if(Compare()(arr[j], arr[j+1]))
            {
                flag = 1;
                swap(arr[j], arr[j+1]);
            }
        }
        if(flag == 0)
            break;
    }
}

int main()
{
    int arr1[] = {3, 7, 5, 2, 1, 9, 6, 4, 8};
    int len1 = sizeof(arr1)/sizeof(arr1[0]);
    BubbleSort<int, Great<int>>(arr1, len1);

    int arr2[] = {3, 7, 5, 2, 1, 9, 6, 4, 8};
    int len2 = sizeof(arr2)/sizeof(arr2[0]);
    BubbleSort<int, Less<int>>(arr2, len2);

    return 0;
}

這裡寫圖片描述

相關推薦

C++迴圈引用仿函式的使用

迴圈引用 #include <iostream> #include <memory.h> #include <boost/shared_ptr.hpp> #in

c++ 中minmax 函式

包含在c++標準庫中標頭檔案中,在標頭檔案<windows.h>中定義了min,max的巨集,若在包含的同時包含<windows.h>會導致函式無法使用。 <windows.h>提供了_cpp_min等函式來代替min函式的功能。 C++11標準:

c++的引用指標

c++的引用和指標 簡略分析c++的引用和指標之間的聯絡和區別。 1.引用 引用:就是某一變數(目標)的一個別名,對引用的操作與對變數直接操作完全一樣。 引用的宣告方法: 型別識別符號 &引用名=目標變數名; 例:char ch;

C++靜態成員靜態函式

C++類的靜態成員變數是需要初始化的,實際上不是為了初始化而初始化,本質上是要定義,分配記憶體。需要在類的外部進行定義。 靜態成員變數: 靜態成員變數和常用的全域性變數比較類似。 先看一個頭檔案animal.h #ifndef DUOTAIJINGTAI_ANIMAL_H #defi

c/c++靜態變數靜態函式

c語言中 c語言中需要記憶體來存放資料。而記憶體主要分為兩類:靜態儲存區和動態儲存區; 靜態儲存區分為:只讀資料(READONLY DATA)區、以讀寫資料(RW DATA)區、未初始化區(BSS)。它們都是在程式編譯連線階段確定的,在程式執行的階段不會改變。 動

C語言readwrite函式解析

在研究一份AES加密程式碼的時候,發現程式碼從command line獲取資料僅僅使用了read函式,很是疑問。從command line獲取資料不是要使用scanf函式嗎?所以,詳細瞭解了C庫的read函式特性。順帶了write函式,他們是couple一對兒!!! 主要參考文章:h

C++ 謂詞(predicate) 與 仿函式 ( functor (function object))

謂詞與函式物件 謂詞 predicate C++ 標準定義謂詞如下: The Predicate parameter is used whenever an algorithm expects a function object that when applied to the result of

面試題24——C++的引用C語言的指標有什麼區別

C++的引用和C語言的指標有以下區別: (1)引用必須初始化,但是不分配儲存空間。指標不宣告時初始化,在初始化的時候需要分配儲存空間。引用較比指標更加安全; (2)引用指向一塊特定的記憶體,不能被更改。不存在指向空值的引用,但是存在指向空值的指標。指標可指向任意一塊記憶體,可以改變所指的物件

c++中引用指標的區別

指標和引用的區別: (1)當引用被建立時,它必須被初始化。而指標則可以在任何時候被初始化。 (2)一旦一個引用被初始化為指向一個物件,它就不能被改變為對另一個物件的引用。而指標則可以在任何時候指向另一個物件。 (3)不可能有NULL引用。必須確保引用是和一塊合法

C++ 過載運算子過載函式

前言:     運算子過載和函式過載體現了面向物件技術的多型性。多型性機制不僅增加了面向物件軟體系統的靈活性,進一步減少了冗餘資訊,而且顯著提高了軟體的可重用性和可擴充性。     從實現的角度來講,多型性可以劃分為兩類:編譯時的多型性和執行時的多型性。在C+

C++傳引用傳值,傳指標

我們需要傳資料而不改變資料儲存,直接傳值,如int a; 我們需要傳資料,並且改變值大小,需要傳地址,如  int * pa; 我們需要傳資料,並改變數結構中指標的指向,需要傳二級指標,如連結串列中的 node * * l; ... 以前是passl-by-val

C 【printf scanf 函式的使用】

        對於printf函式,我們主要要掌握printf函式的輸出格式。         而對於scanf函式,我們則要知道幾個輸入過程中的錯誤輸入情況和scanf函式的實現原理。  (1)printf 函式    printf 中 格式控制 部分 的完整格式:  

linux c語言 fork() exec 函式的簡介用法

      假如我們在編寫1個c程式時想呼叫1個shell指令碼或者執行1段 bash shell命令, 應該如何實現呢?       其實在<stdlib.h> 這個標頭檔案中包含了1個呼叫shell命令或者指令碼的函式 system();直接把 shell

迴圈引用解決方案

如何處理迴圈引用問題? 什麼是迴圈引用? 顧名思義,兩個物件之間形成環路。對於C++中兩個物件來講,使用智慧指標解決不了這個問題。因為其引用計數不為0。 迴圈引用解決辦法 迴圈引用涉及的問題是垃圾回收(Garbage Collection

C++陣列物件建構函式

定義陣列物件以後,對陣列中的物件初始化的方式分為兩種: 一種方式是在定義的時候用列表初始化 A a[5] = {A(1),A(2),A(3),A(4),A(5)};一種方式是在定義了陣列物件以後,再使

例項講解C語言atanatan2函式

使用時需要預包含#include <math.h> (1)atan(x) 不包括角度的象限資訊,返回值在[-pi/2,pi/2] The atan function computes the principal value of the arc tang

C++中getgetline函式詳解

get函式函式原型有多個,其中比較簡單的2個是:char get(); istream &get(char c);前者提取的字元作為函式值,後者提取的字元賦值給引數c,使用get函式從鍵盤提取自負的格式分別為:cin.get(); cin.get(字元變數c);#in

C#lambda表示式匿名函式

lambda表示式也被稱為匿名函式,何為匿名函式? 匿名沒有真實名字,當然在C#中就是沒有函式名了,C#裡有兩種匿名函式的寫法,一種是早期推出的匿名函式,而另一種就是拉姆達(lambda)表示式了,那麼這兩種有什麼不同,分別怎麼用的,下面介紹一下. 我個人覺得吧,在寫程式碼

C# 靜態類靜態函式

學習靜態類和靜態函式。 這篇部落格的內容來自MSDN,當然內容是我自己看MSDN翻譯出來的。 正文 靜態類和非靜態類其實基本相同。兩者有一處不同:靜態類不能被例項化。換句話來說,你不能夠用new去為一個靜態類例項出一個物件來。因為靜態類中根本沒有例項成

C++中,getgetline函式的區別

cin.getline()和cin.get()都是對輸入的面向行的讀取,即一次讀取整行而不是單個數字或字元,但是二者有一定的區別。 cin.get()每次讀取一整行並把由Enter鍵生成的換行符留在輸入佇列中,比如: #include <iostr