亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

C++帶有指針成員的類處理方式詳解

2020-01-26 13:57:34
字體:
來源:轉載
供稿:網友

在一個類中,如果類沒有指針成員,一切方便,因為默認合成的析構函數會自動處理所有的內存。但是如果一個類帶了指針成員,那么需要我們自己來寫一個析構函數來管理內存。在<<c++ primer>> 中寫到,如果一個類需要我們自己寫析構函數,那么這個類,也會需要我們自己寫拷貝構造函數和拷貝賦值函數。

析構函數:

我們這里定義一個類HasPtr,這個類中包含一個int 類型的指針。然后定義一個析構函數,這個函數打印一句話。

HasPtr.h 類的頭文件

#pragma once#ifndef __HASPTR__#define __HASPTR__class HasPtr{public: HasPtr(int i,int *p); //HasPtr& operator=(HasPtr&); //HasPtr(const HasPtr&); ~HasPtr(); int get_ptr_value(); void set_ptr_value(int *p); int get_val(); void set_val(int v);private: int val; int *ptr;};#endif // !__HASPTR__

HasPtr.cpp 類的實現

#include "stdafx.h"#include <iostream>#include "HasPtr.h"using namespace std;HasPtr::HasPtr(int i, int *p){ val = i; ptr = p;}int HasPtr::get_ptr_value(){ return *ptr;}void HasPtr::set_ptr_value(int *p){ ptr = p;}int HasPtr::get_val(){ return val;}void HasPtr::set_val(int v){ val = v;}HasPtr::~HasPtr(){ cout << "destructor of HasPtr " << endl;}

ClassWithPointer 類,包含main入口,HasPtr在stack上。

// ClassWithPointer.cpp : 定義控制臺應用程序的入口點。//#include "stdafx.h"#include <iostream>#include "HasPtr.h"using namespace std;int main(){ int temp = 100; HasPtr ptr(2,&temp); cout << ptr.get_ptr_value() << endl; cout << ptr.get_val() << endl; system("PAUSE"); system("PAUSE"); return 0;}

執行該入口方法,發現最后還是打印了析構函數這句話,OK,在main 方法中,stack上定義了一個HasPtr,在main方法退出前,析構函數自動調用了。

如果將HasPtr改為動態對象,也就是放在堆上呢?

ClassWithPointer 類,包含main入口,HasPtr在heap上。

// ClassWithPointer.cpp : 定義控制臺應用程序的入口點。//#include "stdafx.h"#include <iostream>#include "HasPtr.h"using namespace std;int main(){ int temp = 100; //HasPtr ptr(2,&temp); HasPtr *ptr = new HasPtr(2,&temp); cout << ptr->get_ptr_value() << endl; cout << ptr->get_val() << endl; system("PAUSE"); return 0;}

執行一下,發現析構函數沒有調用。OK,我們在return 0前面添加一個delete ptr; 析構函數執行了。

所以,這里有兩個結論:

  • 當一個對象在stack 上時,析構函數自動調用。
  • 當一個對象在heap上時,需要調用delete 語句,析構函數才會被執行。

現在在析構函數中調用delete 語句來刪除指針成員。

頭文件不變,HasPtr.cpp 文件代碼如下:

 #include "stdafx.h"#include <iostream>#include "HasPtr.h"using namespace std;HasPtr::HasPtr(int i, int *p){ val = i; ptr = p;}int HasPtr::get_ptr_value(){ return *ptr;}void HasPtr::set_ptr_value(int *p){ ptr = p;}int HasPtr::get_val(){ return val;}void HasPtr::set_val(int v){ val = v;}HasPtr::~HasPtr(){ cout << "destructor of HasPtr " << endl; delete ptr;}

 ClassWithPointer 代碼如下:

// ClassWithPointer.cpp : 定義控制臺應用程序的入口點。//#include "stdafx.h"#include <iostream>#include "HasPtr.h"using namespace std;int main(){ int temp = 100; HasPtr ptr(2,&temp); cout << ptr.get_ptr_value() << endl; cout << ptr.get_val() << endl; system("PAUSE"); return 0;}

執行一下,正常打印結束后,拋出錯誤:

這里說明delete 不能刪除stack 上的指針值。

現在在ClassWithPointer傳入一個動態指針來測試一下。

// ClassWithPointer.cpp : 定義控制臺應用程序的入口點。//#include "stdafx.h"#include <iostream>#include "HasPtr.h"using namespace std;int main(){int temp = 100;HasPtr ptr(2,&temp);cout << ptr.get_ptr_value() << endl;cout << ptr.get_val() << endl;system("PAUSE");return 0;}

執行后析構函數正常運行。所以這里有兩個結論:

  • delete 語句不能刪除stack 上的指針值。
  • delete 語句只能刪除heap上的指針值,也就是new 出來的對象。 

默認拷貝構造函數和默認賦值操作:

這里我們調用默認的構造函數和默認的賦值操作,看看會出現什么,為了方便查看,我在析構函數中打印了當前對象的地址,以及在main方法中打印了對象地址,這樣就可以看到哪個對象調用了析構函數:

HasPtr.cpp 代碼如下:

#include "stdafx.h"#include <iostream>#include "HasPtr.h"using namespace std;HasPtr::HasPtr(int i, int *p){ val = i; ptr = p;}int HasPtr::get_ptr_value(){ return *ptr;}void HasPtr::set_ptr_value(int *p){ ptr = p;}int HasPtr::get_val(){ return val;}void HasPtr::set_val(int v){ val = v;}HasPtr::~HasPtr(){ cout << "destructor of HasPtr " << this << endl; delete ptr;}

ClassWithPointer 代碼如下:

// ClassWithPointer.cpp : 定義控制臺應用程序的入口點。//#include "stdafx.h"#include <iostream>#include "HasPtr.h"using namespace std;int main(){ int *temp = new int(100); HasPtr ptr(2,temp); cout << "ptr-------------->" << &ptr << endl; cout << ptr.get_ptr_value() << endl; cout << ptr.get_val() << endl;  HasPtr ptr2(ptr); cout << "ptr2-------------->" << &ptr2 << endl; cout << ptr2.get_ptr_value() << endl; cout << ptr2.get_val() << endl;  HasPtr ptr3 = ptr; cout << "ptr3-------------->" << &ptr3 << endl; cout << ptr3.get_ptr_value() << endl; cout << ptr3.get_val() << endl; system("PAUSE"); return 0;}

運行結果如下,最后還是報錯了:

其實程序運行到第二個析構函數時,報錯了。報錯原因是,ptr 其實已經是pending指針了,因為這個ptr 指針所指向的地址已經被delete了。

不過我們這里最起碼可以知道默認的拷貝構造函數和賦值操作,也是會直接復制指針值的,不是指針所指向的值。是指針變量的值,也就是地址。

所以這里引申出來的問題是:如何管理對象中指針成員的內存? 這個是一個核心問題。

上面的例子,就是默認的方式,但是管理失敗了,因為析構函數到最后會刪除pending 指針,導致異常發生。 

智能指針:

引入一個類U_Ptr,用來管理我們需要在業務對象中需要的指針變量,假設為int *p。頭文件如下:

#pragma once#ifndef __UPTR__#define __UPTR__#include "HasPtr.h"#include <iostream>using namespace std;class U_Ptr{ friend class HasPtr; int *ip; size_t use; U_Ptr(int *p):ip(p),use(1) {} ~U_Ptr()  {  cout << "destruction:"<< *ip << endl;  delete ip; }};#endif // !__UPTR__

現在我們的業務對象還是HasPtr。頭文件如下:

#pragma once#ifndef __HASPTR__#define __HASPTR__#include "U_Ptr.h"class HasPtr{public: HasPtr(int *p, int i):ptr(new U_Ptr(p)),val(i){} HasPtr(const HasPtr &orgi) :ptr(orgi.ptr), val(orgi.val)  {  ++ptr->use;   cout << "coming into copy construction:" << ptr->use << endl; } HasPtr& operator=(const HasPtr &rhs); ~HasPtr(); int get_ptr_value() const; int get_int() const; void set_ptr(int *p); void set_int(int i);private: U_Ptr *ptr; int val;};#endif // !__HASPTR__

HasPtr.cpp 實現如下:

#include "stdafx.h"#include "HasPtr.h"#include <iostream>using namespace std;HasPtr& HasPtr::operator=(const HasPtr &rhs){ ++rhs.ptr->use; if (--ptr->use == 0) {  delete ptr; } ptr = rhs.ptr; val = rhs.val; return *this;}HasPtr::~HasPtr(){ cout << "destruction:" << ptr->use << endl; if (--ptr->use == 0) {  delete ptr; }}int HasPtr::get_ptr_value() const{ return *ptr->ip;}int HasPtr::get_int() const{ return val;}void HasPtr::set_ptr(int *p){ ptr->ip = p;}void HasPtr::set_int(int i){ val = i;} 

測試類如下:

// SmartPointer.cpp : 定義控制臺應用程序的入口點。//#include "stdafx.h"#include "HasPtr.h"#include <iostream>using namespace std;int main(){ int *temp = new int(100); HasPtr ptr(temp,22); cout << "ptr------------>" << endl; cout << ptr.get_ptr_value() << endl; cout << ptr.get_int() << endl; HasPtr ptr2(ptr); cout << "ptr2------------>" << endl; cout << ptr2.get_ptr_value() << endl; cout << ptr2.get_int() << endl; system("PAUSE"); return 0;} 

我們把U_Ptr 叫做智能指針,用于幫我們管理需要的指針成員。我們的業務對象HasPtr對象包含一個智能指針,這個指針在HasPtr 對象創建時創建,智能指針的use 變量用來記錄業務對象HasPtr對象被復制了多少次,也就是說,有多少個相同的指針指向了ptr所指向的地方。如果要記錄HasPtr對象一共有多少個一樣的,那么就需要在拷貝構造函數和賦值操作處進行對use變量加一操作,在析構函數處進行減一操作。當減到0時,刪除指針。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
91在线网站视频| 不卡av电影在线观看| 欧美电影《睫毛膏》| 啪一啪鲁一鲁2019在线视频| 91大神福利视频在线| 精品久久久久久久久中文字幕| 91地址最新发布| 97久久伊人激情网| 成人免费大片黄在线播放| 日韩精品中文字幕在线播放| 国产人妖伪娘一区91| 亚洲国产小视频| 欧美激情视频一区二区| 国产精品2018| 欧美激情视频三区| 日韩精品免费电影| 国产欧美一区二区| 色悠悠久久88| 国产一区私人高清影院| 亚洲精品国产精品国产自| 久久久精品国产| 欧美性xxxxhd| 日韩欧美在线国产| 欧美电影免费观看| 成人国产精品久久久久久亚洲| 日韩中文在线视频| 久久亚洲春色中文字幕| 精品国产成人在线| 成人h猎奇视频网站| 91精品视频免费观看| 97超碰国产精品女人人人爽| 成人国产精品久久久| 亚洲另类激情图| 国产一区二区黑人欧美xxxx| 日韩成人黄色av| 992tv在线成人免费观看| 欧美成在线视频| 九色91av视频| 国产亚洲综合久久| 日韩在线视频免费观看| 亚洲女人被黑人巨大进入| 九九精品视频在线| 国产视频精品在线| 亚洲福利在线看| 国产精品永久免费视频| 国产97色在线| 国产精品视频xxxx| 91精品国产综合久久久久久蜜臀| 国产一区二区三区中文| 97在线看免费观看视频在线观看| 亚洲精品之草原avav久久| 国产精品免费一区豆花| 欧美精品一区二区三区国产精品| 久热国产精品视频| www国产精品视频| 国产精品色悠悠| 国产成人一区二区在线| 在线午夜精品自拍| 亚洲aⅴ男人的天堂在线观看| 久久精品中文字幕| 色黄久久久久久| 欧美高跟鞋交xxxxxhd| 欧美日本在线视频中文字字幕| 亚洲欧美福利视频| 久久精品99久久久香蕉| 欧美国产亚洲精品久久久8v| 久久亚洲精品中文字幕冲田杏梨| 亚洲深夜福利网站| 国产视频亚洲视频| 日韩美女写真福利在线观看| 国产中文欧美精品| xxav国产精品美女主播| 欧美怡红院视频一区二区三区| 欧美性猛交xxxx偷拍洗澡| 亚洲日韩中文字幕| 日韩欧美亚洲一二三区| 国产精品吹潮在线观看| 国产亚洲欧美日韩精品| 色青青草原桃花久久综合| 日韩一区视频在线| 亚洲的天堂在线中文字幕| 亚洲精品在线看| 久久久久www| 国产一区二区在线免费| 精品国产鲁一鲁一区二区张丽| 欧美香蕉大胸在线视频观看| 国产精品久久婷婷六月丁香| 亚洲色图五月天| 91精品视频网站| 在线播放亚洲激情| 国产精品v片在线观看不卡| 日韩成人在线视频网站| 亚洲欧洲一区二区三区久久| 97在线视频免费看| 亚洲最大在线视频| 亚洲性日韩精品一区二区| 国产一区二区三区精品久久久| 欧美性色视频在线| 青青在线视频一区二区三区| 国产精品视频在线播放| 亚洲男人的天堂在线| 亚洲tv在线观看| 成人免费视频a| 91热精品视频| 国产一区二区三区视频在线观看| 国产成人啪精品视频免费网| 亚洲国产精品久久久| 丰满岳妇乱一区二区三区| 久久久人成影片一区二区三区观看| 欧美性色xo影院| 国产91精品青草社区| 成人黄色免费网站在线观看| 国产欧美va欧美va香蕉在线| 日韩精品中文字幕在线播放| 91性高湖久久久久久久久_久久99| 国产精品99久久久久久久久久久久| 尤物tv国产一区| 欧美中文在线观看国产| 欧美日韩一区二区免费视频| 欧美激情精品久久久久久蜜臀| 欧美激情亚洲一区| 日韩有码在线观看| 欧美精品成人在线| 日韩久久精品电影| 国产精品尤物福利片在线观看| 国产精品久久久久福利| 欧美肥老太性生活视频| 亚洲美女又黄又爽在线观看| 久久久久久久久综合| 国产黑人绿帽在线第一区| 日韩欧美精品中文字幕| 精品色蜜蜜精品视频在线观看| 精品成人69xx.xyz| 日韩在线观看视频免费| 国产脚交av在线一区二区| 国产日韩在线看| 国产精品久久999| 国产热re99久久6国产精品| 欧美精品videos另类日本| 国产精品27p| 国产精品成人免费视频| 国产成人久久精品| 亚洲国产一区二区三区在线观看| 欧美乱妇高清无乱码| 国产69精品久久久久久| 欧美性猛交xxxx偷拍洗澡| 国产精品久久久久久婷婷天堂| 精品无码久久久久久国产| 欧美国产日韩在线| 日韩美女免费线视频| 国产成人精品视| 亚洲а∨天堂久久精品9966| 久久久久久国产免费| 91日本在线视频| 欧美小视频在线观看| 欧美极度另类性三渗透| 亚洲成人激情在线| 日本精品久久中文字幕佐佐木| 欧美激情伊人电影| 日韩av电影手机在线| 国产精品电影一区| 狠狠躁18三区二区一区| 色综合伊人色综合网站| 一区二区欧美在线|