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++ 中min和max 函式
包含在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語言read和write函式解析
在研究一份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語言atan和atan2函式
使用時需要預包含#include <math.h> (1)atan(x) 不包括角度的象限資訊,返回值在[-pi/2,pi/2] The atan function computes the principal value of the arc tang
C++中get和getline函式詳解
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++中,get和getline函式的區別
cin.getline()和cin.get()都是對輸入的面向行的讀取,即一次讀取整行而不是單個數字或字元,但是二者有一定的區別。 cin.get()每次讀取一整行並把由Enter鍵生成的換行符留在輸入佇列中,比如: #include <iostr