重载“=”结合自由存储区 遇到的问题

M0605050215 2010-01-04 10:24:38
class SimpleCircle
{
public:
SimpleCircle();
SimpleCircle(int);
~SimlpeCircle();
void SetRadius(int);
int GetRadius();
SimpleCircle& operator = (const SimpleCircle&)
private:
int *itsRadius;
};

SimpleCircle& SimpleCircle(const SimpleCirecle& rhs)
{
if(this == &rhs)
reurn *this;
delete itsRadius;
itsRadius = new int;
*itsRadius = rhs.GetRadius();
}

问题一 :1.为什么要判断this指针与rhs是否同指一个内存块?书上说的是防止由于“a=a”而导致的程序崩溃。请解释哈
程序是怎么崩溃的??但是c++中,eg:int a; a = a;是合法的啊?
2.如果把SimepleCircle成员变量改为int itsRadius;是不是可以不用判断??也就是说是不是自由存储区扰的祸?

问题二 :先delete itsRadius(这是删去其构造函数申请的自由存储区);然后又用new申请一块内存。。。这样做是何必呢?感觉多此一举。这两句话能不能省?


谢谢、、、、、
...全文
73 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
macrojj 2010-01-05
  • 打赏
  • 举报
回复

问题一 :1.为什么要判断this指针与rhs是否同指一个内存块?书上说的是防止由于“a=a”而导致的程序崩溃。请解释哈
程序是怎么崩溃的??但是c++中,eg:int a; a = a;是合法的啊? 他们都说了,int a会没关系 值语义的
2.如果把SimepleCircle成员变量改为int itsRadius;是不是可以不用判断??也就是说是不是自由存储区扰的祸?是啊

问题二 :先delete itsRadius(这是删去其构造函数申请的自由存储区);然后又用new申请一块内存。。。这样做是何必呢?感觉多此一举。这两句话能不能省?所有权的改变
走好每一步 2010-01-05
  • 打赏
  • 举报
回复
我说的也许太泛,如果你是个编程爱好者,就花心思去琢磨。
如果仅仅为了以后工作的话,就不需要了,毕竟许多人也不用明白这些也照样混得好!

为什么要用到类?或者类产生的原因?
你可以这样答:因为数据封装,信息隐藏,继承,多态。但假如一开始发明类的作者一下子让类拥有如此多的好属性,我只能说他是计算机中的神!
这种答案是很不负责任的答案。
一开始类并不是这样的,只不过不断地对它加工,才成为今天这样子。

声明一下:我还是学生,以后还要为找工作发愁!
走好每一步 2010-01-05
  • 打赏
  • 举报
回复
1.那就是说我把那个重载“=”的函数写成:
SimpleCircle& SimpleCircle(const SimpleCirecle& rhs)
{

*itsRadius = rhs.GetRadius();
}
即可???
答:可以自己去设计下实验验证自己的想法。“=”号运算符重载和初始化估计是不一样的。

2. 由于构造函数写成:

SimpleCircle::SimpleCircle()
{
itsRadius = new int;
}

SimpleCircle::SimepleCircle(int a)
{
insRadius = new int(a);
}

为了防止内存泄露我们必须自定义析构函数 SimpleCircle::~SimpleCircle(){delete insRadius;} 而不能用默认的析构函数??看到书上用的是默认的析构函数,我觉得那么做会导致内存泄露,,,,请问有必要自定义析构函数??
答:析构函数的作用:把程序员自己开辟堆空间的内存释放掉。你这个例子用到了堆,肯定要自己定义析构函数了。默认析构函数的定义是:什么都不做。或者你可以认为没有默认析构函数。

当然我说的也不一定对,不过有一点你要清楚的,类到底在内存中是如何表示的、怎样存放。如果能体会类是由栈和堆加上代码区的话(静态变量区比较特殊了),估计许多困惑就会消除。
我老师以前跟我说过一句话:能紧紧抓住内存,就能明白c。我觉得这句话对c++也适用。如果离开内存,谈论c++也是很肤浅了。(个人观点,仅供参考)像c++许多拗口的概念,联系下内存,你会发现没有那么多花样。因为花样只是文字游戏,表达会有歧义。但是联系内存后,因为是实在东西,你不会误会它了。
M0605050215 2010-01-05
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 tajon1226 的回复:]
1.为什么要判断this指针与rhs是否同指一个内存块?书上说的是防止由于“a=a”而导致的程序崩溃。请解释哈答:首先要明确&引用的本质。引用是指针,不能改变的指针。rhs变量里面放的是引用对象的首地址。
this指针放的是本对象的首地址。假如 对象a = 对象a,也就是说rhs存放的是对象a的首地址,
delete itsRadius;
、、a对象的内存1被释放掉了,rhs引用里面的值即a对象的首地址没变,但当然不能通过它来读取a对象了。
itsRadius = new int;
、、重新给a对象分配内存2,
*itsRadius = rhs.GetRadius();
、、把内存1的东西赋给内存2,显然是不行的,内存1已经被释放掉了。

2.如果把SimepleCircle成员变量改为int itsRadius;是不是可以不用判断??也就是说是不是自由存储区扰的祸?
答:确实不用判断了。而且引用也没必要用了。自己去做下实验吧,我说的也不一定对。


问题二 :先delete itsRadius(这是删去其构造函数申请的自由存储区);然后又用new申请一块内存。。。这样做是何必呢?感觉多此一举。这两句话能不能省
答:你那个例子本身就不好,通过一个不好的例子去说明一个比较难理解的问题是不可取的。
如果你想像一下,对象a中 new int [3],可能要放12字节某内容,而rhs引用的对象却new int [100]放的是400字节的内容, 对象a = rhs。 那肯定放不下的啦,所以说那new在本例子中是多次一举,在我说的例子中确是必须的。
[/Quote]

1.那就是说我把那个重载“=”的函数写成:
SimpleCircle& SimpleCircle(const SimpleCirecle& rhs)
{

*itsRadius = rhs.GetRadius();
}
即可???

2. 由于构造函数写成:

SimpleCircle::SimpleCircle()
{
itsRadius = new int;
}

SimpleCircle::SimepleCircle(int a)
{
insRadius = new int(a);
}

为了防止内存泄露我们必须自定义析构函数 SimpleCircle::~SimpleCircle(){delete insRadius;} 而不能用默认的析构函数??看到书上用的是默认的析构函数,我觉得那么做会导致内存泄露,,,,请问有必要自定义析构函数??



走好每一步 2010-01-04
  • 打赏
  • 举报
回复
1.为什么要判断this指针与rhs是否同指一个内存块?书上说的是防止由于“a=a”而导致的程序崩溃。请解释哈 答:首先要明确&引用的本质。引用是指针,不能改变的指针。rhs变量里面放的是引用对象的首地址。
this指针放的是本对象的首地址。假如 对象a = 对象a,也就是说rhs存放的是对象a的首地址,
delete itsRadius;
、、a对象的内存1被释放掉了,rhs引用里面的值即a对象的首地址没变,但当然不能通过它来读取a对象了。
itsRadius = new int;
、、重新给a对象分配内存2,
*itsRadius = rhs.GetRadius();
、、把内存1的东西赋给内存2,显然是不行的,内存1已经被释放掉了。

2.如果把SimepleCircle成员变量改为int itsRadius;是不是可以不用判断??也就是说是不是自由存储区扰的祸?
答:确实不用判断了。而且引用也没必要用了。自己去做下实验吧,我说的也不一定对。


问题二 :先delete itsRadius(这是删去其构造函数申请的自由存储区);然后又用new申请一块内存。。。这样做是何必呢?感觉多此一举。这两句话能不能省
答:你那个例子本身就不好,通过一个不好的例子去说明一个比较难理解的问题是不可取的。
如果你想像一下,对象a中 new int [3],可能要放12字节某内容,而rhs引用的对象却new int [100]放的是400字节的内容, 对象a = rhs。 那肯定放不下的啦,所以说那new在本例子中是多次一举,在我说的例子中确是必须的。
arong1234 2010-01-04
  • 打赏
  • 举报
回复
当长度一样时,填进新值不就把左值冲掉了?为什么必须delete再new?
[Quote=引用 4 楼 huiguixian 的回复:]
问题二 :先delete itsRadius(这是删去其构造函数申请的自由存储区);然后又用new申请一块内存。。。这样做是何必呢?感觉多此一举。这两句话能不能省?
这里所说的就是上面所说的,先把左操作数里面的内容删除
然后重新分配空间,把右操作数赋值给他
不是多余的,是必须的!
[/Quote]
arong1234 2010-01-04
  • 打赏
  • 举报
回复
关于1:如果不做这个判断,下面代码就有问题,因为rhs就是自己,delete itsRadius已经使原来的radius被释放,itsRadius= new int又开辟一个新的,紧接着的 *itsRadius = rhs.GetRadius();等于啥都不作(自己给自己赋值),因此最终的结果使这样做过以后,itsRadius指向一个没初始化的内存

delete itsRadius;
itsRadius = new int;
*itsRadius = rhs.GetRadius();

关于2:如果没有释放、重分配过程,是的,你可以不判断。但是养成判断的习惯是好的,因为即使所有赋值是安全的,假如你又大量的赋值过程,也是一种浪费

再分配对于你这种情况确实无必要。new当且仅当其指向的内存大小发生变化时才有必要

[Quote=引用楼主 m0605050215 的回复:]
class SimpleCircle
{
    public:
      SimpleCircle();
      SimpleCircle(int);
      ~SimlpeCircle();
      void SetRadius(int);
      int GetRadius();
      SimpleCircle& operator = (const SimpleCircle&)
    private:
      int *itsRadius;
};

SimpleCircle& SimpleCircle(const SimpleCirecle& rhs)
{
    if(this == &rhs)
        reurn *this;
    delete itsRadius;
    itsRadius = new int;
    *itsRadius = rhs.GetRadius();
}

问题一 :1.为什么要判断this指针与rhs是否同指一个内存块?书上说的是防止由于“a=a”而导致的程序崩溃。请解释哈
    程序是怎么崩溃的??但是c++中,eg:int a; a = a;是合法的啊?
        2.如果把SimepleCircle成员变量改为int itsRadius;是不是可以不用判断??也就是说是不是自由存储区扰的祸?

问题二 :先delete itsRadius(这是删去其构造函数申请的自由存储区);然后又用new申请一块内存。。。这样做是何必呢?感觉多此一举。这两句话能不能省?


谢谢、、、、、
[/Quote]
小小攻城师 2010-01-04
  • 打赏
  • 举报
回复
问题二 :先delete itsRadius(这是删去其构造函数申请的自由存储区);然后又用new申请一块内存。。。这样做是何必呢?感觉多此一举。这两句话能不能省?
这里所说的就是上面所说的,先把左操作数里面的内容删除
然后重新分配空间,把右操作数赋值给他
不是多余的,是必须的!
小小攻城师 2010-01-04
  • 打赏
  • 举报
回复
问题一 :1.为什么要判断this指针与rhs是否同指一个内存块?书上说的是防止由于“a=a”而导致的程序崩溃。请解释哈
这个首先是要判断的
加入赋值是要把左边的消掉,然后把右边的赋值给左操作数
假如你没有判断,直接把左操作数删除,左操作数所动态分配的空间都被释放了
相当于右操作数的空间也被释放了
你这样再赋值,原来的东西,指针动态分配的空间都没有了。当然就产生错误了。
sonnno 2010-01-04
  • 打赏
  • 举报
回复
mark
lirg8405 2010-01-04
  • 打赏
  • 举报
回复
也许是this指针的问题吧,我也不清楚;
不先删除的话,再new 一个,那么原来的那块内在就无法释放了

64,675

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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