一个简单的C++问题

yangshun2008 2009-05-25 03:20:00
大家讨论一下,为什们下面这段代码在VC6.0和VS2005下运行都不会有问题,根据c++ primer 4th(中文版) page421的说明这段代码运行应该会有错,不知道vc和vs做了怎样的处理使得这个错误没有发生。
#include <iostream>
#include <string>

using namespace std;
class Test
{
private:
int *p ;

public:
Test(int *ip) : p(ip) { }
void setval(int val) { *p = val;}
int getval() const{ return *p; }
};

void main()
{
int *ip = new int(20);
Test t(ip);
delete ip;
ip = NULL;
t.setval(10);
cout << t.getval() << endl;
return ;
}
...全文
211 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
wbgxx 2009-05-25
  • 打赏
  • 举报
回复
顶 一楼的!!!!!!!!!
Sou2012 2009-05-25
  • 打赏
  • 举报
回复
up..
hjs2009 2009-05-25
  • 打赏
  • 举报
回复
不好意思,补充一下,上面回答有一点问题。

delete ip,与 ip = null 还是有区别的。

如下所示;

#include <iostream>
#include <string>

using namespace std;
class Test
{
private:
  int *p ;

public:
  Test(int *ip) : p(ip) { }
  void setval(int val) { *p = val;}
  int getval() const{ return *p; }
  void printValue(){printf("0x%x\n", this->p);
};

void main()
{
int *ip = new int(20);
Test t(ip);
t.printValue(); //此时打印结果应该为 20;
*ip = 50;
ip = NULL;
t.printValue(); //此时打印结果应该为 50
delete ip;
t.printValue(); //此时打印结果应该为一个未知值。
t.setval(10);
cout < < t.getval() < < endl;
return ;
}


hjs2009 2009-05-25
  • 打赏
  • 举报
回复
楼主提这样的问题,说明楼主对C中的指针的了解还需加强啊。

在初始化TEST类似,把IP的地址初始化给P,这个时候指针P跟指针IP指向同一个地址,假设这个地址是 0x12345678,这个时候内存地址
0x12345678的内容为 20, 当 delete ip 的时候,这个时候实际是是回收IP的指针,在C++, 实际上是相当于把IP的地址设为0,这个时候
P指向的地址为0x12345678, IP指向的地址为0,二者的内容均不相同。

IP = NULL 这个程序语句实际上是没有意义的。不需要考虑,并且C++中,支持对空指针进行 delete 操作,不会引发异常的。

所以最后打印结果为10,因为IP指向听位置内容没有改变。

如果这样测试,例程如下:
#include <iostream>
#include <string>

using namespace std;
class Test
{
private:
  int *p ;

public:
  Test(int *ip) : p(ip) { }
  void setval(int val) { *p = val;}
  int getval() const{ return *p; }
  void printValue(){printf("0x%x\n", this->p);
};

void main()
{
int *ip = new int(20);
Test t(ip);
t.printValue(); //此时打印结果应该为 20;
*ip = 50;
delete ip;
ip = NULL;
t.printValue(); //此时打印结果应该为 50
t.setval(10);
cout < < t.getval() < < endl;
return ;
}
zhan1094 2009-05-25
  • 打赏
  • 举报
回复
学习~~
tangshuiling 2009-05-25
  • 打赏
  • 举报
回复

如果楼主拜读过Scott Meyers的<<effective c++>>,其中谈到一个著名的设计原则叫懒人原则,意思是
不到事到临头就懒的去管。
内存的分配和释放也是一样,操作系统就利用了懒人原则,其它用户只要不指明用到某某内存,操作系统就不
会去管它,是否被释放好像与我操作系统暂时无关,你要用就用吧,反正懒的理。
windsting 2009-05-25
  • 打赏
  • 举报
回复
原文我看了,书上根本没有说运行会有错啊,原文是:

这里的问题是 ip 和 ptr 的指针指向同一对象,删除了该对象时,ptr中的指针不再指向有效
对象,然而,没有办法的值对象已经不存在了。

vc根本不需要作任何处理,这段代码就可以编译通过,
一般来说还能表现的像你写的那样可以预期,虽然不总如此。
yangshun2008 2009-05-25
  • 打赏
  • 举报
回复
我觉得C++的delete操作只是把已用的内存的地址重新归还给操作系统的空闲列表,而这个地址中存放的内容是没有清掉的,而地址中存放的内容被清掉是在你再次使用这个内存地址的时候。
大家可以讨论一下我的说法是否正确......
yangshun2008 2009-05-25
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 goodname 的回复:]
简单的来说代码等价于如下模型(不是源程序的翻译,希望不要误导了)
int *ip = new int(20);
int *Test_ip = ip;
delete ip;

ip = NULL;

*Test_ip = 10;//Test_ip仍然指向那个地址,所以可以赋值。这里Test_ip应该是野指针,使用了已经释放的内存。
[/Quote]

void main()
{
int *ip = new int(20);
Test t(ip);
delete ip;
ip = NULL;
t.setval(10);
cout < < t.getval() < < endl;
return ;
}
1楼的说法是正确的,对象t的成员变量p确实已经是一个野指针,它指向的是原来ip的指向的地址,可是此时已经delete ip;如果我们修改main():
void main()
{
int *ip = new int(20);
Test t(ip);
delete ip;
ip = NULL;
t.setval(10);
// int *pp = new int(-100);
ip = new int(20);
cout << t.getval() << endl;
return ;
}
会发现输出的是20,如果把注释去掉,输出的却是-100了。
leegongbo 2009-05-25
  • 打赏
  • 举报
回复
UP~
[Quote=引用 4 楼 fengxuxing 的回复:]
C/C++ code#include "stdafx.h"
#include <iostream>
#include <string>

using namespace std;
class Test
{
private:
int *p ;

public:
Test(int *ip) : p(ip) { }
void setval(int val) { *p = val;}
int getval() const{ return *p; }
};

void main()
{
int *ip = new int(20);
Test t(ip);
delete ip;
ip = NULL;
t.setval(10);

ip = new int(20);//lz你加一行在这里,新分配…
[/Quote]
lpf000 2009-05-25
  • 打赏
  • 举报
回复
void setval(int val) { *p = val;cout<<*p<<"10"<<endl}
这样你main函数中的输出就无效了,可能是无效内存是一次性的吧。。。
pengzhixi 2009-05-25
  • 打赏
  • 举报
回复
ip = NULL;
t.setval(10);
int *str=new int(30);//加上这句再看看.
cout < < t.getval() < < endl;
pengzhixi 2009-05-25
  • 打赏
  • 举报
回复
只能说这是运气而已,在ip被delete时,Test成员p已经成为了野指针了.但是它指向的那块内存还没有被其他程序修改而已.所以对它的一切操作看起来很正常而已.
woods2001 2009-05-25
  • 打赏
  • 举报
回复
学习了·· 所谓的野指针~
dl591944556 2009-05-25
  • 打赏
  • 举报
回复
Test t(ip); delete ip;使得*ip释放了空间而后t.setval(10) 指向得不到*p=10;
sun451989 2009-05-25
  • 打赏
  • 举报
回复
#include <iostream> 
#include <string>

using namespace std;
class Test
{
private:
int *p ;

public:
Test(int *ip) : p(ip) { }
void setval(int val) { *p = val;}
int getval() const{ return *p; }
};

void main()
{
int *ip = new int(20);
Test t(ip);
delete ip;
ip = NULL; //这里只是把ip指针赋0,但是t对象里的p指针还是指向的20
t.setval(10); //通过t对象的p指针还是可以修改内存(20),(因为还是有指针指向那个20内存)
cout < < t.getval() < < endl; //同样也可以读
return ;
}
dl591944556 2009-05-25
  • 打赏
  • 举报
回复
其原因可能是堆被损坏
Qlaiaqu 2009-05-25
  • 打赏
  • 举报
回复
#include "stdafx.h"
#include <iostream>
#include <string>

using namespace std;
class Test
{
private:
int *p ;

public:
Test(int *ip) : p(ip) { }
void setval(int val) { *p = val;}
int getval() const{ return *p; }
};

void main()
{
int *ip = new int(20);
Test t(ip);
delete ip;
ip = NULL;
t.setval(10);

ip = new int(20);//lz你加一行在这里,新分配的内存似乎与类中保存的指针已经没有关系了,但是数据却被修改了

cout << t.getval() << endl;
return ;
}

对于指针来讲,编译器不会检测其合法性,你可以用,如果恰好没有使用这块内存,那么这个程序自然安全,如果不小心用了,比如程序中我加的一行,那么数据就会变成未知的,这难道还不是错误吗?
fairchild811 2009-05-25
  • 打赏
  • 举报
回复
一楼说的正解,虽然是不合理的使用,但是输出结果是不会错的
fairchild811 2009-05-25
  • 打赏
  • 举报
回复
为什么会有错啊,是因为ip先被删除,再被设为NULL,这个和后面的setval没关系吧,t还在
加载更多回复(1)

65,211

社区成员

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

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