@rg070836rg
2015-08-16T15:11:44.000000Z
字数 2544
阅读 2963
data_structure
从自由存储为 type-name 的对象或对象数组分配内存,并将已适当分类的非零指针返回到对象。
包含new运算符的表达式执行三类操作:
new 运算符调用函数 operator new,为数组以及基本类型对象分配存储
类对象可基于每个类定义其自己的 operator new 静态成员函数。
当编译器遇到用于分配类型 type 的对象的 new 运算符时,它将发布对 type::operator new( sizeof( type ) )
的调用。因此,new 运算符可以为对象分配正确的内存量。
如果不成功,则 new 将返回零或引发异常(std::bad_alloc)
例如下面的测试:
#include <iostream>
using namespace std;
#define NUM 500000000
int main() {
int *p = new int[NUM];
if (p == 0x0) {
cout << "内存不足" << endl;
system("pause");
}
else
{
cout << "分配成功" << endl;
system("pause");
}
return 0;
}
当调整数据较小时(350000000),可以分配成功.
后修改测试代码,
for (int i = 0; ;i++)
{
int *p = new int[10000];
if (p == 0x0) {
cout << "内存不足" << endl;
system("pause");
}
}
发现,少量多次分配,基本不会出现大问题。程序可以分配到2G内存之后,报出std::bad_alloc异常。
现在换到VC平台,调用分配大块内存,默认为抛出0,而不是异常。
来自微软中国
处理失败的内存分配要求的方法:
编写自定义恢复例程来处理此类失败,然后通过调用 _set_new_handler 运行时函数来注册您的函数。
用于删除用new申请的空间,释放空间块。
- 使用对象的 delete 运算符释放其内存。 在对象中删除后取消引用指针的程序,可能会有不可预知的结果或崩溃。
- 当 delete用于释放C++类对象的内存时,对象的析构函数会在释放对象内存前调用 (如果对象具有析构函数)。
- 如果对 delete运算符的操作的是一个可修改的左值,那么在对象删除后其值是未定义的。
如:
delete L.head;
L.head=NULL;
那么问题来了:为什么在delete L.head后,还需要赋值为空,是否多余?
测试:
int main() {
int *p = new int;
*p=5;
delete p;
p=NULL;
}
1、在执行了new之后,返回一个地址给p,
2、然后,p赋值5;
3、接下来delete p;值变成未知值。
但注意!这边并没有把p给释放掉,也就是说,p仍然指向了,一个内存单元,与之前的区别在于,原来那个单元是我自己申请的,属于我管,但是,现在我不想要了, 把他扔掉了,那这块就不归我管了,就好比把房子卖了,保存了钥匙。实际上,程序“应该”已经不具备管理这个内存单元的权利,但是我却没把权利完全给交出去一样.所以,一旦有其他程序,利用了这个内存单元(好比其他人把房子买了过去),而我恰巧操作不当,使用了这个本身不归我管理的“钥匙”,那么就会造成程序的紊乱。(换句话说,就是指向内存块不合法!)
4、因此,我们需要执行第四步,置空。
这样,就不会产生野指针,造成紊乱。
当所指向的对象被释放或者收回,但是对该指针没有作任何的修改,以至于该指针仍旧指向已经回收的内存地址,此情况下该指针便称悬垂指针。
1、 在许多编程语言中,显示地从内存中删除一个对象或者返回时通过销毁栈帧,并不会改变相关的指针的值。该指针仍旧指向内存中相同的位置,即使指针所指的内容已经被删除。一旦误操作该指针,会导致错误。
2、 当一个指针指向的内存被释放后就会变成悬垂指针。可以避免这个问题的一种方法是在释放它的引用后把指针重置为NULL。
引入智能指针可以防止垂悬指针出现。一般是把指针封装到一个称之为智能指针类中,这个类中另外还封装了一个使用计数器,对指针的复制等操作将导致该计数器的值加1,对指针的delete操作则会减1,值为0时,指针为NULL
这是与悬垂指针相对立的一个问题。
memory leak指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费。
举个简单的例子:
定义一个节点类,然后一次生成5个节点。进行一些操作。
struct Node
{
int a;
Node* next;
};
void main()
{
Node *pHead=new Node;
pHead->a=0;
pHead->next=NULL;
Node *p=pHead;
for (int i=0;i<5;i++)
{
p->next=new Node;
p=p->next;
p->a=i+1;
}
p->next=NULL;
while (pHead)
{
cout<<pHead->a<<endl;
pHead=pHead->next;
}
}
程序理所当然的运行了:
结果看上去也没错,输出了5个值。
但是请注意,如果还有后续操作,会发现,根本找不到之前的元素了!
这就产生了内存泄露,那些元素除非是在程序运行结束,否则空间根本不可能被释放!这是小程序,看不出来,如果在一个大程序中也犯如此低级错,那么程序将消耗巨额内存。