程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++中的auto_ptr智能指針的感化及應用辦法詳解

C++中的auto_ptr智能指針的感化及應用辦法詳解

編輯:關於C++

C++中的auto_ptr智能指針的感化及應用辦法詳解。本站提示廣大學習愛好者:(C++中的auto_ptr智能指針的感化及應用辦法詳解)文章只能為提供參考,不一定能成為您想要的結果。以下是C++中的auto_ptr智能指針的感化及應用辦法詳解正文


智能指針(auto_ptr) 這個名字聽起來很酷是否是?其實auto_ptr 只是C++尺度庫供給的一個類模板,它與傳統的new/delete掌握內存比擬有必定優勢,但也有其局限。本文總結的8個成績足以涵蓋auto_ptr的年夜部門內容。

 auto_ptr是甚麼?

auto_ptr 是C++尺度庫供給的類模板,auto_ptr對象經由過程初始化指向由new創立的靜態內存,它是這塊內存的具有者,一塊內存不克不及同時被分給兩個具有者。當auto_ptr對象性命周期停止時,其析構函數會將auto_ptr對象具有的靜態內存主動釋放。即便產生異常,經由過程異常的棧睜開進程也能將靜態內存釋放。auto_ptr不支撐new 數組。

該類型在頭文件memory中,在法式的守舊經由過程 #include<memory> 導入,接上去講授該智能指針的感化和應用。

應用辦法:

  auto_ptr<type> ptr(new type()); 這是該指針的界說情勢,個中 type 是指針指向的類型,ptr 是該指針的稱號。

  好比該type 是int,詳細界說以下:

  auto_ptr<int> ptr(new int(4));

  好比該type 是map<int,vector<int> >,詳細界說以下:

  auto_ptr<map<int,vector<int> > > ptr(new map<int,vector<int> > ());

  固然可以先界說,後賦值,以下所示:

  auto_ptr<map<int,int> > ptr;
  ptr = auto_ptr<map<int,int> >(new map<int,int> ());

感化1:包管一個對象在某個時光只能被一個該品種型的智能指針所指向,就是平日所說的對象一切權。

感化2:對指向的對象主動釋放的感化,概況看以下代碼。

代碼片斷一:

#include <iostream>
#include <string.h>
#include <memory>
#include <string>
#include <Windows.h>
#include <map>
#include <ctime>
#include <vector>
using namespace std;#define MAXN 20000000
class test_ptr
{
public:
map<int,int> *p;
test_ptr()
{
p = new map<int,int>();
for(int i = 0;i<MAXN;i++)
p->insert(make_pair(i,i));
}
};
int main(int argc,char *argv[])
{
for(int i = 0;i<100;i++)
{
Sleep(1000);
cout << i << endl; // 輸入 創立次數
test_ptr * tmp = new test_ptr();
}
system("pause");
return 0;
} 


在某些情形下,能夠我們就會寫出下面的代碼來,經由過程運轉會發明存在內存溢出。關於一些經歷老道的法式員能夠會作以下改寫:

代碼片斷二:

#include <iostream>
#include <string.h>
#include <memory>
#include <string>
#include <Windows.h>
#include <map>
#include <ctime>
#include <vector>
using namespace std;
#define MAXN 20000000
class test_ptr
{
public:
map<int,int> *p;
test_ptr()
{
//p = auto_ptr<map<int,int> > (new map<int,int>());
p = new map<int,int>();
for(int i = 0;i<MAXN;i++)
p->insert(make_pair(i,i));
}
~test_ptr()
{
delete p;
}
};
int main(int argc,char *argv[])
{
for(int i = 0;i<100;i++)
{
Sleep(1000);
cout << i << endl; 
test_ptr * tmp = new test_ptr();
}
system("pause");
return 0;
} 

在test_ptr 類中的析構函數中添加內存釋放代碼,然則在main函數中,界說的部分指針,政府部指針掉效時其實不會主動挪用析構函數,在這類情形下也會招致內存洩露成績。固然,假如仔細的法式員可以在 test_ptr * tmp = new test_ptr() 前面加上一句 delete tmp ,如許也可以或許釋放內存,不會湧現內存洩露成績。然則在某些情形下,很輕易漏寫,為懂得決此成績,auto_ptr 就可以施展感化了。

代碼片斷三:

#include <iostream>
#include <string.h>
#include <memory>
#include <string>
#include <Windows.h>
#include <map>
#include <ctime>
#include <vector>
using namespace std;
#define MAXN 20000000
class test_ptr
{
public:
map<int,int> *p;
test_ptr()
{
p = new map<int,int>();
for(int i = 0;i<MAXN;i++)
p->insert(make_pair(i,i));
}
~test_ptr()
{
delete p;
}
};
int main(int argc,char *argv[])
{
for(int i = 0;i<100;i++)
{
Sleep(1000);
cout << i << endl; //輸入創立次數
auto_ptr<test_ptr> tmp = auto_ptr<test_ptr> (new test_ptr());
}
system("pause");
return 0;
} 

在main函數中,創立test_ptr類型指針時,該指針是auto_ptr 類型的智能指針,當智能指針掉效時,會主動挪用該類的析構函數。所以這類寫法可以不再顯示挪用delete 語句了。然則該智能指針也只是包管挪用類的析構函數,假如析構函數並沒有釋放類中聲明的變量,那該怎樣辦。

代碼片斷四:

#include <iostream>
#include <string.h>
#include <memory>
#include <string>
#include <Windows.h>
#include <map>
#include <ctime>
#include <vector>
using namespace std;
#define MAXN 20000000
class test_ptr
{
public:
//auto_ptr<map<int,int> > p;
map<int,int> *p;
test_ptr()
{
//p = auto_ptr<map<int,int> > (new map<int,int>());
p = new map<int,int>();
for(int i = 0;i<MAXN;i++)
p->insert(make_pair(i,i));
}
/*
~test_ptr()
{
delete p;
}
*/
};
int main(int argc,char *argv[])
{
for(int i = 0;i<100;i++)
{
Sleep(1000);
cout << i << endl; //輸入創立次數
auto_ptr<test_ptr> tmp = auto_ptr<test_ptr> (new test_ptr());
}
system("pause");
return 0;
}

在這類情形下,照樣會湧現內存洩露成績,為懂得決該成績,對類中聲明的指針也是須要聲明為auto_ptr類型。

代碼片斷五:

#include <iostream>
#include <string.h>
#include <memory>
#include <string>
#include <Windows.h>
#include <map>
#include <ctime>
#include <vector>
using namespace std;
#define MAXN 20000000
class test_ptr
{
public:
auto_ptr<map<int,int> > p;
test_ptr()
{
p = auto_ptr<map<int,int> > (new map<int,int>());
for(int i = 0;i<MAXN;i++)
p->insert(make_pair(i,i));
}
};
int main(int argc,char *argv[])
{
for(int i = 0;i<100;i++)
{
Sleep(1000);
cout << i << endl; //輸入創立次數
auto_ptr<test_ptr> tmp = auto_ptr<test_ptr> (new test_ptr());
}
system("pause");
return 0;
}

如許就不消顯示界說類的析構函數,不消在內部顯示挪用delete函數,固然假如盡早挪用delete函數也是可以的,盡早釋放內存也比該指針掉效再釋放好一些,這些就是為了避免忘卻挪用。

經由過程如上剖析:可以得出以下結論。

1 界說了智能指針,當智能指針掉效時會主動挪用類的析構函數。

2 在 類中界說的智能指針,不用在析構函數中顯示的delete,當內部挪用該類的析構函數時,會主動釋放該智能指針指向的對象,釋放內存。

3 假如類中界說的是智能指針,然則內部沒有觸發類中的析構函數挪用,該智能指針指向的對象照樣不克不及釋放。

auto_ptr 智能指針的bug

auto_ptr 智能指針在c++ 11 尺度中曾經被擯棄,被擯棄的緣由就是由於該bug。後面也提到過,一個對象只能被一個智能指針所援用,如許就會招致一個賦值成績。看以下代碼

代碼片斷六:

#include <iostream>
#include <string.h>
#include <memory>
#include <set>
using namespace std;
#define MAXN 20000000
void pri(auto_ptr<set<int> > p)
{
set<int>::iterator ite = p->begin();
for(;ite!=p->end();ite++)
{
cout << *ite << endl;
}
}
int main(int argc,char *argv[])
{
auto_ptr<set<int> > ptr(new set<int> ());
for(int i = 0;i< 3;i++)
{
int a;
cin >> a;
ptr->insert(a);
}
pri(ptr);
pri(ptr);
system("pause");
return 0;
}

初看這代碼沒甚麼成績,不外運轉法式會瓦解。這就是該智能指針最年夜的bug, 在法式32行 挪用pri(ptr) ,法式到這並沒甚麼成績,然則第二次挪用pri(ptr) 時法式就會瓦解。緣由就是後面講過,一個對象智能被一個智能指針所指向,在第一次挪用pri()函數時,為了包管這一准繩,當把ptr指針傳入pri函數時,法式外部就把ptr置為空,所以到第二次挪用時,就會湧現瓦解的情形。關於這類情形的處理之道就是應用shared_ptr 指針(該指針的道理是經由過程援用計數器來完成的)。

假如要應用shared_ptr 智能指針,須要裝置boost庫,該庫還包含很多其他功效。有興致的可以測驗考試以下,該類中的智能指針照樣比擬好用。也不存在許多其他bug。

以上所述是小編給年夜家引見的C++中的auto_ptr智能指針實例詳解,願望對年夜家有所贊助,假如年夜家有任何疑問請給我留言,小編會實時答復年夜家的。在此也異常感激年夜家對網站的支撐!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved