转载:C++函数中new一块内存,作为返回值

Posted on 2018-02-27 16:48  supercxm  阅读(1207)  评论(0编辑  收藏  举报

转载来自:http://blog.itpub.net/7728585/viewspace-2123621/

今天遇到一个问题,C++编程时,函数中new一块内存,然后将申请内存的指针作为返回值。怎么delete内存?

首先明白几个基础
1、函数按值传递和按值返回的时候都会调用复制构造函数
2、一般在函数体内定义的栈变量是不能返回其地址或者引用给主调函数的,因为在函数结束的时候这些栈变量将释放
3、可以使用new的方式建立堆内存的方式,然后返回引用或者指针,因为new这种方式建立的堆内存并不随函数的结束而结束,
     而指针变量释放但是指针本生的值已经返回。同时也可以按值放回,但是这种情况下将可能出现内存泄露
来看下面的代码

/*************************************************************************
    > File Name: testcc.cpp
    > Author: gaopeng
    > Mail: gaopp_200217@163.com 
    > Created Time: Thu 01 Sep 2016 09:06:53 PM CST
 ************************************************************************/

#include<iostream>
using namespace std;


class testa
{
        private:
                int i;
        public:
                testa(const int m){
                        cout<<"create a object\n";
                        i=m;
                }
                const int& geti() const {
                        return i;
                } 
                testa(const testa& m ){
                        cout<<"copy funcation\n";
                        i=m.i;
                }
                ~testa(){
                        cout<<"discard a object\n";
                }
                testa operator=(const testa& c)
                {
                        cout<<"= funcation\n";
                        i = c.i;
                }

};

testa func() 
{
        cout<<"in func function\n";
        //testa p(10);
        testa* p = new testa(1);
        cout<<p<<endl;
        cout<<"end func\n";
        return *p;
}


int main(void)
{
        testa m = func(); //copy 
        cout<<&m<<endl;
        cout<<m.geti()<<endl;
        return 0;
}
View Code

程序说明:
这里testa* p = new testa(1);建立一块堆内存
这里return *p;按值返回,按值返回会调用复制构造函数给值赋予给新建个对象m
程序结束后调用m的析构函数,但是这里new出来的内存空间已经没有可以指向的指针
因为p已经释放,而返回的是*p,这块内存已经泄露。我们跑一下看看:
in func function   --调用func函数
create a object   --new创建的testa的堆内存 testa* p = new testa(1);
0x1914010        --new的地址 cout<<p<<endl;
end func           --结束func函数 cout<<"end func\n";
copy funcation   --按值返回调用复制构造函数,将值赋予给新的变量m testa m = func();
0x7fffb9c438a0  --新对象m的地址cout<<&m<<endl;
1
discard a object  --析构函数释放栈对象m的空间

这里我们发现new的堆内存空间没有被析构,那么内存已经泄露。
那么我们怎么不大量改变程序的情况下来消除这种问题呢
当然是使用指针或者引用来返回。

testa* func() 
{
        cout<<"in func function\n";
        //testa p(10);
        testa* p = new testa(1);
        cout<<p<<endl;
        cout<<"end func\n";
        return p;
}


int main(void)
{
        {
                testa* m = func(); //copy 
                cout<<m<<endl;
                cout<<m->geti()<<endl;
                delete m;
        }
        return 0;
}
View Code

这一在main中我把定义m指针到删除放到了一个block中,这样在block结束的时候就释放了m避免了空指针的存在。
下面是引用。

testa& func() 
{
        cout<<"in func function\n";
        //testa p(10);
        testa* p = new testa(1);
        cout<<p<<endl;
        cout<<"end func\n";
        return *p;
}


int main(void)
{
        {
                testa& m = func(); //copy 
                cout<<&m<<endl;
                cout<<m.geti()<<endl;
                delete &m;
        }
        return 0;
}
View Code

同样main中的这个程序块是为了避免空引用
输出如下:
in func function  
create a object
0x1989010
end func
0x1989010   
1
discard a object

可以看到地址都相同,最后的析构函数是我调用delete执行的。

Copyright © 2024 supercxm
Powered by .NET 8.0 on Kubernetes