C++的new 操作符问题疑惑?

hisense2423 2008-02-27 10:02:02
各位,
最近在看一些C++程序,经常使用new操作符来创建对象,但是基本上没有程序判断new操作符返回的指针是否为空的操作(类似于C语言中的malloc等),请问这是为什么啊,难道new创建的对象永远不可能为空吗?请达人指点,谢谢。
...全文
1458 37 打赏 收藏 转发到动态 举报
写回复
用AI写文章
37 条回复
切换为时间正序
请发表友善的回复…
发表回复
红尾黄花鱼 2008-03-01
  • 打赏
  • 举报
回复
每一处都考虑返回值实在是太辛苦了
hong8292 2008-02-29
  • 打赏
  • 举报
回复
引用:林锐的《高质量程序设计指南 C++语言》

--------------------------------------------

里面的观点不能说全不对,但至少有好几个是错误的。
yangb2014# 2008-02-29
  • 打赏
  • 举报
回复
这就是有的程序只能在实验室下好使,一旦大规模应用就老出问题的原因之一,
lokibalder 2008-02-29
  • 打赏
  • 举报
回复
new 是会有返回空值的情况,就是内存不够的时候,但是概率很小
在win98之后,使用了虚拟内存,所以内存不够的时候,硬盘就会起到内存的作用,所以很难耗尽内存,只是速度会明显减慢
Tracy2007 2008-02-29
  • 打赏
  • 举报
回复

建议楼主看林锐的《高质量程序设计指南 C++语言》
里面讲的很好
jeckpc 2008-02-29
  • 打赏
  • 举报
回复
大家说得都很有道理,很深刻,继续学习中!

wsidnow 2008-02-28
  • 打赏
  • 举报
回复
不太清楚了,是不是因为不会有NEW空的情况而避之.
楼上的解都挺高的,学习 了..
paerxiushi 2008-02-28
  • 打赏
  • 举报
回复
1.如果在你的程序中经常使用大对象复制操作的话,极有可能出现内存不够用的情况,例如定义如下一个函数模板:
template<class T>
T print(T a)
{
T b=a;
return T;
}
调用时使用:
CWinApp c=print(app)
如果T类型是一个像CWinApp那么大型的对象,这个函数至少执行了四次大对象的复制与赋值工作:
1.从把外部对象转给模板形参时,会复制临时的CWinApp对象给a
2.将a赋给b时,就进行了一次CWinApp的赋值操作。
3.函数返回对象时,会复制临时的未命名CWinApp对象,
4.而当函数调用完毕后,又把临时对象赋给了对象c;
因此在调用函数的时,经常使用模板形参的const引用,
template<class T>
T& print(const T& a)
{
T b=a;
return T;
}
这样就执行了两次复制工作。
如果大型使用了对象的复制操作,会导致new操作无法分配内存的情况。此后指针会赋成0值,表示分配失败,因分配失败异常类型为bad_alloc,它定义在stdexcept头文件中。

2.在有些情况下,必须捕捉new操作产生的异常:
如果你定义了一个类,它使用了一个指针作为数据成员。在构造函数使用初始化式对指针初始化,例如:
class IntPtr
{
private:
int a;
int* p;
public:
IntPtr(int* ip=0,int a=0) try:p(new int(0)),a(0)
{
}
catch(bad_alloc e)
{
cout<<e.what()<<endl;
}
}
为了保证对象的一致性,你需要在catch语句块中,撤销每个已初始过的成员

3.在为指针分配内存之前,往往将指针赋值成0,指针值为0,等同于为NULL的情况。在使用delete删除指针后,因为指针所代表的地址仍然存在,需要将指针赋成0,以免回收资源时报错:
int *p=0;
p=new int(0);
delete p;
p=0; //如果不将指针赋值为0,那么在别处判断指针是否为效时,就会因为两次使用delete而出错。
在别的函数中对于判断同一指针p:
if(p)
delete p;

4.如果在定义new操作符时,使用:
void operator delete[](void* ptr) throw();
如果在分配时出现错误,那异常说明是因为发生不符合要求的错误,那么系统会调用unexcepted函数,它也会调用terminate函数而中止程序。因此只定义一个承诺不会报错的new操作符往往是不明智的。







peter_han2008 2008-02-28
  • 打赏
  • 举报
回复
以后看来要多注意了,呵呵
sxd269 2008-02-28
  • 打赏
  • 举报
回复
new 一般是内存分配失败抛异常。如果当你的系统真正一点内存都new不出来,你捕获异常之后,有用吗?
herman~~ 2008-02-28
  • 打赏
  • 举报
回复
写一个create成员,返回值bool,来判断成功或者失败
构造函数仅仅做简单的初始化工作

我都是这样
hong8292 2008-02-28
  • 打赏
  • 举报
回复
to coooore:

vc6.0,很久没有用过了~~HOHO~~而且曾经用vc6.0的时候还只会C~~
从学c++开始就没有用vc6.0了~~
vc6.0太老了,很多方面都于ISO C++差的太远了~~
现在就算工作需要用MS的编译器,也是用vs2005了,除了极少对标准还不支持外,还是不错的~~


to Lz:
放弃vc6.0吧!
laowang2 2008-02-28
  • 打赏
  • 举报
回复
顶顶
hisense2423 2008-02-27
  • 打赏
  • 举报
回复
谢谢各位的指点,确实是,内存充足的情况下,大概99%以上的地方都不用判断new的返回值,但是当申请一些占用较大系统资源的对象时候,可能是要对返回值进行判断了。当然,具体是处理异常,还是判断返回值,可能不同的上下文情况下会有不同的考虑。
hastings 2008-02-27
  • 打赏
  • 举报
回复
当你new会失败时,你的计算机之前已经有症状了:
运行变慢,甚至死机。
chenyu2202863 2008-02-27
  • 打赏
  • 举报
回复
要做到返回值得检查,这是良好的习惯
星羽 2008-02-27
  • 打赏
  • 举报
回复

普通new一个异常的类型std::bad_alloc。这个是标准适应性态。在早期C++的舞台上,这个性态和现在的非常不同;new将返回0来指出一个失败,和malloc()非常相似。

在一定的环境下,返回一个NULL指针来表示一个失败依然是一个不错的选择。C++标准委员会意识到这个问题,所以他们决定定义一个特别的new操作符版本,这个版本返回0表示失败。

一个nothow new语句和普通的new语句相似,除了它的变量将涉及到std::nothrow_t。Class std::nothrow_t在new将按照下面的方式来定义:

class nothrow_t // in namespace std
{}; //empty class

Operator nothrow new is declared like this:

//declarations from <new>
void * operator new (size_t size, const std::nothrow_t &);
//array version
void * operator new[] (size_t size, const std::nothrow_t &);

In addition, <new> defines a const global object of type nothrow_t:

extern const nothrow_t nothrow; //in namespace std

按照这个方式,调用nothrow new的代码将可以使用统一的变量名字。比如:

#include <new>
#include <iostream> // for std::cerr
#include <cstdlib> // for std::exit()
Task * ptask = new (std::nothrow) Task;
if (!ptask)
{
std::cerr<<"allocation failure!";
std::exit(1);
}
//... allocation succeeded; continue normally

但是,你可以注意到你创建了你自己的nothrow_t对象来完成相同的效应:



#include <new>
std::nothrow_t nt;
Task * ptask = new (nt) Task; //user-defined argument
if (!ptask)
//...


星羽 2008-02-27
  • 打赏
  • 举报
回复

int* p = new(nothrow) int[0x1ffffffe];
if (p == 0)
return 1;
Chappell 2008-02-27
  • 打赏
  • 举报
回复
try
{
new操作
}
catch (...)
{
做一些资源释放
再次new
}
sheenl 2008-02-27
  • 打赏
  • 举报
回复
正常的new不会返回空, 只是抛出异常, 所以不需要判断是否为NULL。除非你强行设成nothrow模式
加载更多回复(17)

64,676

社区成员

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

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