class HasPtr{
public:
HasPtr(const int &p,int i):ptr(new int(p)),val(i){}
HasPtr(const HasPtr &Hp):ptr(new int(*Hp.ptr)),val(Hp.val){}
HasPtr& operator=(const HasPtr&);
~HasPtr(){delete ptr;} //错误源
int *get_ptr() const {return ptr;}
int get_int() const {return val;}
void set_ptr(int *p){ptr=p;}
void set_int(int i){val=i;}
int get_ptr_val() const {return *ptr;}
void set_ptr_val(int val) const {*ptr=val;}
private:
int* ptr;
int val;
};
#include <iostream>
#include "HasPtr_value_type.H"
using namespace std;
int main()
{
int i=50;
int j=66;
HasPtr Hp1(i,50);
Hp1.set_ptr(&j);
return 0;//出现错误:d:\dd\err.exe
File:dbgheap.c
Line:1132
Expression: _CrtIsValidHeapPointer(pUserData
}
原因:错误在最后的return语句中产生,产生于类的析构函数
类删除ptr指针时释放了在类外部申请的内存(j存放的堆地址),所以发生错误
此类错误的原理类似于悬垂指针问题
C++ Primer中的建议是使用智能指针或值型类(本类中应用的就是值型类)
值型类中每次赋予类的对象指针成员时都要new一个新的地址,这样不管怎样处理都不会和外部发生冲突
若要安全实现本例,可以改加粗的语句为
Hp1.set_ptr(new int(j));
但必须做这样的更改也说明set_ptr这条成员函数是多余且不安全的
因为类的设计者不能保证类的用户不用外部指针赋值给内部指针,所以应该去掉这个接口
回复Comments
{commenttime}{commentauthor}
{CommentUrl}
{commentcontent}