关于CArray传值方式发生运行时错误

pois 2013-05-08 10:40:24
项目很复杂,我简化了下代码

class A
{
int *m_a;
public:
A()//不带参数构造函数,只是为了通过编译
{
int fenge = 4;
};
A(int n)//我需要用的构造函数
{
m_a = new int;
m_a[0] = n;
}
A(A& _a)//深度拷贝构造函数
{
m_a = new int;
}
~A()//析构,清理成员指针
{
delete m_a;
}
};


	CArray <A,A> arr;//先不考虑用引用及指针
A a(1); //构造对象0x0012ff2c
arr.Add(a);// 看下面解释,一共生成了3个对象,一个加入到array中
int fenge = 10;//断点分割
arr.RemoveAt(0);//析构加入到array的那个对象,调用析构,delete野指针出错
fenge = 9;


Add时生成三个对象
深度拷贝构造函数 0x0012fe2c
深度拷贝构造函数 0x0012fd10
不带参数构造函数 0x00369ee8

之后两次调用析构函数 删除 0x0012fd10,0x0012fe2c,也就是说,两个有效对象被carray删掉了,一个垃圾对象进了array,然后RemoveAt时delete野指针出错

...全文
193 11 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
lm_whales 2013-05-31
  • 打赏
  • 举报
回复
delete 一个正常分配的内存,或者空指针不会出错;不需要保护。 如果为了保险,加保护也未尝不可,------防止其他操作破坏了内存管理系统,或者内存硬件错误,产生的异常,------不过这么做是否,有点过于,杞人忧天了。呵呵!
pois 2013-05-30
  • 打赏
  • 举报
回复
引用 4 楼 lm_whales 的回复:
你这个类A写的很可怕,给你改一下:

class A{
    int *m_a;
public:
    A():m_a(NULL){};
    A(int n):m_a(NULL){  create(n); };
    A(const A& a):m_a(NULL){  init(a.m_a);  };
    A& operator =(const A& a){
      if(&a==this)return *this; //防止自赋值
      init(a.m_a);  
      return *this;
    };       
    ~A(){ delete m_a; };
private:
    void create(int n){
        try { m_a = new int;}
        catch(...){}  
        if(m_a) *m_a= n; 
    };
    void destory(){delete m_a;
         m_a=NULL;
    };
    void init(const int *a){ 
         if(a)  create(*a);
         else destory();
    };    
};
然后你在试验一下;
对的,感谢~
yaozhiyong110 2013-05-30
  • 打赏
  • 举报
回复
release下 A a; A b(a) b的拷贝构造调用 init里的destory m_n是NULL还是有效指针?
lm_whales 2013-05-30
  • 打赏
  • 举报
回复
因为这个类太简单, delete 一个正常分配的内存,或者空指针不会出错;不需要保护。 构造函数加保护,是因为, 构造函数抛出异常,没有办法处理。 并且不能保证new,不会抛出异常;注意抛出异常后,不能保证 m_a =NULL; 所以,构造函数中,一律先初始化为NULL; 虽然那种情况,非常极端,只有内存耗尽才会出现。
yaozhiyong110 2013-05-30
  • 打赏
  • 举报
回复
引用 6 楼 yaozhiyong110 的回复:
[quote=引用 4 楼 lm_whales 的回复:] 你这个类A写的很可怕,给你改一下:

class A{
    int *m_a;
public:
    A():m_a(NULL){};
    A(int n):m_a(NULL){  create(n); };
    A(const A& a):m_a(NULL){  init(a.m_a);  };
    A& operator =(const A& a){
      if(&a==this)return *this; //防止自赋值
      init(a.m_a);  
      return *this;
    };       
    ~A(){ delete m_a; };
private:
    void create(int n){
        try { m_a = new int;}
        catch(...){}  
        if(m_a) *m_a= n; 
    };
    void destory(){delete m_a;
         m_a=NULL;
    };
    void init(const int *a){ 
         if(a)  create(*a);
         else destory();
    };    
};
然后你在试验一下;
init只是拷贝构造才调用 A a; A b(a) debug下 destory里的m_a也不为NULL delete前不舍得加保护 就要保证指针一定是有效的...[/quote] 应该是release下不为NULL debug下应该是NULL
yaozhiyong110 2013-05-30
  • 打赏
  • 举报
回复
引用 4 楼 lm_whales 的回复:
你这个类A写的很可怕,给你改一下:

class A{
    int *m_a;
public:
    A():m_a(NULL){};
    A(int n):m_a(NULL){  create(n); };
    A(const A& a):m_a(NULL){  init(a.m_a);  };
    A& operator =(const A& a){
      if(&a==this)return *this; //防止自赋值
      init(a.m_a);  
      return *this;
    };       
    ~A(){ delete m_a; };
private:
    void create(int n){
        try { m_a = new int;}
        catch(...){}  
        if(m_a) *m_a= n; 
    };
    void destory(){delete m_a;
         m_a=NULL;
    };
    void init(const int *a){ 
         if(a)  create(*a);
         else destory();
    };    
};
然后你在试验一下;
init只是拷贝构造才调用 A a; A b(a) debug下 destory里的m_a也不为NULL delete前不舍得加保护 就要保证指针一定是有效的...
yaozhiyong110 2013-05-30
  • 打赏
  • 举报
回复
引用 4 楼 lm_whales 的回复:
你这个类A写的很可怕,给你改一下:

class A{
    int *m_a;
public:
    A():m_a(NULL){};
    A(int n):m_a(NULL){  create(n); };
    A(const A& a):m_a(NULL){  init(a.m_a);  };
    A& operator =(const A& a){
      if(&a==this)return *this; //防止自赋值
      init(a.m_a);  
      return *this;
    };       
    ~A(){ if(m_a)delete m_a; };
private:
    void create(int n){
        try { m_a = new int;}
        catch(...){}  
        if(m_a) *m_a= n; 
    };
    void destory(){delete m_a;
         m_a=NULL;
    };
    void init(const int *a){ 
         if(a)  create(*a);
         else destory();
    };    
};
然后你在试验一下;
析构为什么不加保护?
lm_whales 2013-05-30
  • 打赏
  • 举报
回复
你这个类A写的很可怕,给你改一下:

class A{
    int *m_a;
public:
    A():m_a(NULL){};
    A(int n):m_a(NULL){  create(n); };
    A(const A& a):m_a(NULL){  init(a.m_a);  };
    A& operator =(const A& a){
      if(&a==this)return *this; //防止自赋值
      init(a.m_a);  
      return *this;
    };       
    ~A(){ delete m_a; };
private:
    void create(int n){
        try { m_a = new int;}
        catch(...){}  
        if(m_a) *m_a= n; 
    };
    void destory(){delete m_a;
         m_a=NULL;
    };
    void init(const int *a){ 
         if(a)  create(*a);
         else destory();
    };    
};
然后你在试验一下;
信阳毛尖 2013-05-09
  • 打赏
  • 举报
回复
pois 2013-05-08
  • 打赏
  • 举报
回复
class A
{
	int *m_a;
public:
	A()
	{
		int fenge = 4;
	};
	A(int n)
	{
		m_a = new int;
		m_a[0] = n;
	}
	A(A& _a)
	{
		*this = _a;
	}
	~A()
	{
		delete m_a;
	}
	A &operator=(A &_a)
	{
		m_a = new int;
		return *this;
	}
};
构造第三个对象0x00369ee8(也就是进队列的对象)后,调用=操作符 顺便测试了下以引用方式定义array CArray <A,A &> arr; A a(1); // 构造对象 0x0012ff2c arr.Add(a); // 直接调用无参数构造函数,调用=操作符,跳过中间两个临时对象 int fenge = 10; arr.RemoveAt(0); fenge = 9;
pois 2013-05-08
  • 打赏
  • 举报
回复
解决了,再重载操作符=作深度拷贝

16,547

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • AIGC Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧