首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

c++ 析构函数解决思路

2013-08-16 
c++ 析构函数下面的代码,编译能通过,但是运行的话会输出很多东西,怀疑是析构函数出了问题。但是想不明白为

c++ 析构函数
下面的代码,编译能通过,但是运行的话会输出很多东西,怀疑是析构函数出了问题。
但是想不明白为什么?以下是我的代码:


#include <iostream>

using namespace std;
//class Screen;
class Screen{
};
class U_Ptr {
    friend class ScreenPtr;
    U_Ptr(Screen *p):ip(p){}
    Screen *ip;
    ~U_Ptr() {delete ip;}//当把这行注释掉的话,运行就没有问题
};
class ScreenPtr {
    public:
        ScreenPtr(Screen *p):ptr(new U_Ptr(p)) {}
        ~ScreenPtr() {delete ptr;}
    private:
        U_Ptr *ptr;
};
int main()
{
    Screen myScreen;
    ScreenPtr sc(&myScreen);
    return 0;
}
C++ 类 析构函数
[解决办法]
#include <iostream>

using namespace std;
//class Screen;
class Screen{
};
class U_Ptr {
    friend class ScreenPtr;
    U_Ptr(Screen *p):ip(p){}
    Screen *ip;
    ~U_Ptr() {delete ip;}
};
class ScreenPtr {
    public:
        ScreenPtr(Screen *p):ptr(new U_Ptr(p)) {}
        ~ScreenPtr() {delete ptr;}
    private:
        U_Ptr *ptr;
};
int main()
{
    Screen myScreen;
    //ScreenPtr sc(&myScreen);
    ScreenPtr sc(new Screen());
    return 0;
}

[解决办法]



引用:
那如果ScreenPtr sc(new Screen());和Screen myScreen;ScreenPtr sc(&myScreen);两者并存的话,程序该如何写呢?



各自的析构函数会帮你搞定的,只要你的new的时候 注意 对应delete操作就好好!
注意一一对应
[解决办法]
引用:
Quote: 引用:




Quote: 引用:

那如果ScreenPtr sc(new Screen());和Screen myScreen;ScreenPtr sc(&myScreen);两者并存的话,程序该如何写呢?


各自的析构函数会帮你搞定的,只要你的new的时候 注意 对应delete操作就好好!
注意一一对应

那上面的程序,如果主函数是这样的话:

int main()
{
    Screen myScreen;
    ScreenPtr sc(&myScreen);
    ScreenPtr sc1(new Screen());
    return 0;
}

那么,只能把~U_Ptr() {delete ip;}这句注释掉,运行才没有问题。但是如果注释掉的话,new/delete不就不意义对应了?

此处两者只能有一个接口能正常使用,若使用ScreenPtr sc(&myScreen)则~U_Ptr()析构函数中删除delete ip,否则析构函数不变,但只能使用ScreenPtr sc1(new Screen())这样接口。你可以定义一个static函数如CreateInstance()来指定对象的生成方式,从而定义使用哪种接口。
[解决办法]
引用:

int main()
{
    Screen myScreen;
    ScreenPtr sc(&myScreen); //这里 没有new 操作也进行了delete ip 操作阿!
     //注释掉上面的 ,下面运行没有问题的!
    ScreenPtr sc1(new Screen());
    return 0;
}


保证两个同时成立的话,只有换一个代码结构了!你这样写有问题!
[解决办法]
引用:
那如果ScreenPtr sc(new Screen());和Screen myScreen;ScreenPtr sc(&myScreen);两者并存的话,程序该如何写呢?

略加修改,拷贝一下就好了。


class Screen{
};
class U_Ptr {
    friend class ScreenPtr;
    U_Ptr(Screen *p):ip(p){}
    Screen *ip;
    ~U_Ptr() {delete ip;}
};
class ScreenPtr {
    public:
ScreenPtr(Screen *p):ptr(new U_Ptr(new Screen(*p))) {} //拷贝一下
        ~ScreenPtr() {delete ptr;}
    private:
        U_Ptr *ptr;
};

int main()
{
    
//case 1
Screen myScreen;


    ScreenPtr sc(&myScreen);

//case 2
Screen* p = new Screen();
    ScreenPtr sc2(p);
delete p;
    return 0;
}

 
[解决办法]
引用:
Quote: 引用:

class U_Ptr的构造函数没有new,析构函数中有delete,肯定不对。
class ScreenPtr的构造函数有new,析构函数有delete,正确。
class ScreenPtr缺少了拷贝构造以及赋值重载。这也是不正确的。

ScreenPtr类为什么需要拷贝构造和赋值重载?

类中用了new,拷贝构造和赋值重载必须自己写过,也加上new啊,默认的拷贝构造和=不会帮你new,这样对象拷贝构造和=不正确。使用的时候会发生问题。

[解决办法]
引用:
Quote: 引用:

不能用delete释放栈内存啊老兄

Screen* p = new Screen();这放入栈吗?


指针p在stack内,p指向的对象在heap里。
[解决办法]
引用:
Quote: 引用:

不能用delete释放栈内存啊老兄

Screen* p = new Screen();这放入栈吗?


中间的帖子太多了,没以一一细看,单看你第一帖,你要想在析构函数里释放内存:
class U_Ptr {
    friend class ScreenPtr;
    U_Ptr(Screen *p):ip(p){}
    Screen *ip;
    ~U_Ptr() {delete ip;}//当把这行注释掉的话,运行就没有问题
};


这句:delete ip;
ip指向的必须是堆内存,也就是new出来的才可以,而之所以在这里崩溃,是应为你传进来的是栈内存,这时候就是我所说的“不能用delete释放栈内存啊老兄”
这也就是所谓的new 和 delete 必须匹配

热点排行