c++之智能指针(二)之直接管理内存

来源:互联网 发布:培训管理数据流程图 编辑:程序博客网 时间:2024/05/17 02:43

直接管理内存

c++定义了两个运算符来分配和释放动态内存。new分配内存,delete释放new分配的内存。
相对于智能指针,使用这个两个运算符非常容易出错。因为它不能依赖类对象拷贝、赋值和销毁操作的任何默认定义。

使用new动态分配和初始化对象

默认情况下,动态分配的对象是默认初始化的。这意味着内置类型或组合类型的值将是未定义的。而类类型的对象将用默认的构造函数进行初始化。

string *ps = new string;//ps指向一个动态分配的,初始化为空的stringint *pi = new int;//pi指向一个未初始化的int

也可以使用直接初始化方式或者传统构造方式来初始化一个动态分配的对象。

string *pt = new string("d");//pt指向一个初始化为d的stringint *pd = new int(2048);//pd指向的对象的值为2048

或者对动态分配的对象进行值初始化,只需要在类型名后面跟一个空括号即可。

string *sp = new string();//值初始化为空stringint *dp = new int();//值初始化为0 *dp为0

内存耗尽

一旦一个程序用光了它所有的可用的内存,new表达式就会失败。如果new不能分配所要求的内存空间,他会抛出一个类型为bad_alloc的异常。我们可以改变使用new的方式来阻止它抛出的异常。

//如果分配失败,new抛出std::bad_alloc异常int *p1 = new int;//如果分配时候,new返回一个空指针。int *p2 = new (nothrow) int;

释放动态内存

我们通常使用delete表达式来将动态内存归还给系统。delete表达式接收一个指针,指向我们想要释放的对象。

int i, *pi1 = &i, *pi2 = nullptr;double *pd = new double(33), *pd2 = pd;delete i;//错误,i不是一个指针delete pi1;//未定义,pi1指向一个局部变量delete pd;//正确delete pd2;//未定义,pd2指向的内存已经被释放了delete pi2;//正确,释放一个空指针总是没有错误的

动态对象的生存期直到被释放为止

返回指向动态内存的指针(不是智能指针)的函数给其调用者增加了一个额外的负担—调用者必须记得释放内存。
(忘记释放内存的例子)

    Foo* factory(T arg){        return new Foo(arg);    }    void use_factory(T arg){        Foo *p = factory(arg);        //使用p但是不delete他    }//p离开了他的作用域,但它指向的内存没有释放!

正确的做法:

    void use_factory(T arg){        Foo *p = factory(arg);        //使用p做一些事情        delete p;//释放内存,我们已经不需要它了    }

或者还有一种可能,我们系统中的其他代码要使用use_factory函数所分配的对象,我们就应该修改此函数,让他返回一个指针,指向它分配的内存。

void use_factory(T arg){    Foo *p = factory(arg);    //使用p做一些事情    return p;//调用者在使用完之后,必须释放内存}

delete之后重置指针值

当我们delete一个指针后,指针值就变得无效了。但是在很多机器上指针仍然保存着(已经释放了的)动态内存的地址。在delete之后,指针就变成了人们所说的空悬指针。
如何避免空悬指针呢?在指针即将要离开其作用域之前释放掉它所关联的内存。这样,在指针关联的内存被释放掉之后,就没有机会继续使用指针了。如果我们需要保留指针,可以在delete之后将nullptr赋予指针,这样就清楚的指出指针不指向任何对象。

int *p(new int(42));//p指向动态内存auto q = p;//p和q指向相同的内存delete p;//p和q均变无敌p = nullptr;//指出p不再绑定到任何对象

但是,重置p对q没有任何作用,在我们释放p所指向的(同时也是q所指向的!)内存时,q也变得无效了。

阅读全文
0 0
原创粉丝点击