众所周知,我们在编程的时候经常会在函数中声明局部变量(包括普通类型的变量、指针、引用等等)。

同时,为了满足程序功能的需要,函数的返回值也经常是指针类型或是引用类型,而这返回的指针或是引用也经常指向函数中我们自己声明的局部变量。

这样,程序在某些情况下就可能存在一定的问题。看似很简单的问题,通过仔细的分析,我们就能够更好的理解c++中内存分配和释放的问题。

好,废话不多说,我们进入正题。首先,简单介绍一下程序的内存区域的分配:

程序的内存分配

①堆区(heap)。这一部分主要是由程序开发人员自己通过new和malloc等操作创建的“对象”所保存的内存区域,该区域的变量需要开发人员自己释放。存储方式类似链表。

②栈区(stack)。这一部分主要是程序中的函数所以及其中的变量所占用的内存区域(包括了main函数)。存储方式类似栈。

③全局区或常量区(static)。这一部分主要是存放全局变量、静态数据、常量。程序结束后由系统释放。

④文字常量区。这一部分除妖存放常量字符串。 程序结束后由系统释放。

⑤程序代码区。程序的二进制代码。

1、函数中声明普通变量

void func1()
{
int i;
}

在函数func1()中,我们声明了一个int变量i,它保存在栈区中,当func1执行完成后,i也将被释放。

2、函数中声明指针类型变量

void func2()
{
int *p = (int*)malloc(sizeof(int));
A *a = new A; //A是一个类
}

在函数func2()中,我们声明了一个int型指针变量p和一个用户自定义类A指针变量a,它们都保存在堆区中,在函数func2执行完成后,仍然不会被释放,需要程序开发人员自己使用free()或delete等等进行释放。否则就会导致内存泄漏的问题。

3、函数返回值为指针或引用类型

函数的返回值为指针和引用类型是非常常见而且实用的,如果我们的函数返回的指针或者引用来自函数中声明的指针类型变量,则没有问题。如下:

int* CreatePointerFactory()
{
int *p = (int*)malloc(sizeof(int));
//to do sth here
return p;
}

这样的代码也是常见的简单工厂模式。但是需要注意的是,在通过函数CreatePointerFactory得到指针之后,在完成了相关操作之后,要进行对应的内存释放工作。最后需要将指针的值设置为NULL,防止野指针的产生。

第二种情况,函数返回的指针或者引用来自函数中声明的普通类型变量,则会产生非常严重的问题。如下:

int* getPointer()
{
int i = 1;
//to do sth here
return &i;
} //main.cpp
int* p = getPointer();

因为变量i在栈区创造,在getPointer函数执行结束之后,这片内存区域将被释放,变量i所对应的内存也将被释放掉。因此,如果我们在其他某处(如主函数中)调用了该函数,那么返回得到的指针则是非常危险的,指向的位置是没有任何意义的。

但是,在做实验的时候,我们会发现,此时在某些编译器下,打印*p的值,可能仍是1,有的也可能是乱码。

这里的原因主要如下:

①不同的编译器处理和优化不同。

②OS在释放了这一部分内存之后,并不是完全清空内存中的数据,而只是将标志位flag只为true,表示此块内存是未被占用的。

c++中函数中变量内存分配以及返回指针、引用类型的思考的更多相关文章

  1. 【转载】c++中堆、栈内存分配

    一.内存划分 1.栈区(stack)— 由编译器自动分配释放 ,存放函数参数值,局部变量值等.其操作方式类似于数据结构中栈.2.堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时 ...

  2. (转)C++ STL中的vector的内存分配与释放

    C++ STL中的vector的内存分配与释放http://www.cnblogs.com/biyeymyhjob/archive/2012/09/12/2674004.html 1.vector的内 ...

  3. c++中堆、栈内存分配

    转自:https://blog.csdn.net/qingtingchen1987/article/details/7698415 一个由C/C++编译程序占用内存分为以下几个部分1.栈区(stack ...

  4. Java继承中的转型及其内存分配

    看书的时候被一段代码能凌乱啦,代码是这样的: package 继承; abstract class People { public String tag = "疯狂Java讲义"; ...

  5. 代码中函数、变量、常量 / bss段、data段、text段 /sct文件、.map文件的关系[实例分析arm代码(mdk)]

    函数代码://demo.c #include<stdio.h> #include<stdlib.h> , global2 = , global3 = ; void functi ...

  6. Java实现操作系统中四种动态内存分配算法:BF+NF+WF+FF

    1 概述 本文是利用Java实现操作系统中的四种动态内存分配方式 ,分别是: BF NF WF FF 分两部分,第一部分是介绍四种分配方式的概念以及例子,第二部分是代码实现以及讲解. 2 四种分配方式 ...

  7. Javascript中函数及变量定义的提升

    <html> <head> <title>函数提升</title> <script language="javascript" ...

  8. MIC中函数和变量的声明

    c++/c使用 __declspec(target(mic))函数或变量声明 或 __attribute__((target(mic)))函数或变量声明 举例如下: __attribute__((ta ...

  9. C++变量内存分配及类型修饰符

    前言 了解C++程序内存分配,有助于深刻理解变量的初始化值以及其生存周期.另外,变量类型修饰符也会影响到变量的初始化值及其生存周期.掌握了不同类型变量的初始化值及其生存周期,能够让我们设计程序时定义变 ...

随机推荐

  1. Self-Host Web API 学习笔记

    ASP.NET Web API 不需要 IIS,直接使用控制台程序可以实现. 一.创建一个新的控制台程序,项目名为 HostApi 二.设置目标框架为.NET Framework 4 三.NuGet添 ...

  2. Maven的依赖和传递性质

    1. 引入项目所需jar包 Maven项目直白的一大特点就是一般情况下不需要去自行下载jar包以及目标jar包的依赖包并导入,只需要在去Maven的中央仓库http://mvnrepository.c ...

  3. How to use groovy script on jenkins

    1. Install groovy plugin 2. Add a step of groovy. (normal & systerm) 3. Execute groovy script im ...

  4. linux下常见的字符串处理

    linux下有许多对字符串文本的处理工具,diff,grep,awk,sed等等.. diff 比较两个文件的不同 [root@bogon diff]# diff file1 file2 以高亮的形式 ...

  5. 《Linux内核分析》期末总结

    Linux内核设计期中总结 版权声明:本文为博主原创文章,未经博主允许不得转载. 前八周博客汇总及总结 Linux内核设计第一周——从汇编语言出发理解计算机工作原理 我们学习了汇编语言的基础知识,这一 ...

  6. SQL声明变量并赋值

    declare @studentid int //声明一个int型变量 );//设置变量值,tclass 为任意表,classid 为表中任一字段 if(@studentid is not null) ...

  7. libgdx 裁剪多边形(clip polygon、masking polygon)

    直接放例子代码,代码中以任意四边形为例,如果需要做任意多边形,注意libgdx不能直接用ShapeRender填充多边形,需要先切割成三角形. public static void drawClip( ...

  8. Python学习笔记 for windows 二

    函数 abs(-20)                                        //结果为:20,绝对值函数 def 函数名称([参数1,参数2,参数3]): 执行语句 retu ...

  9. MFC操作excel

    环境:VS2013+office2007 头文件: #pragma once #ifndef __MYEXCEL_H_ #define __MYEXCEL_H_ #include "CApp ...

  10. 显示python已安装模块及路径,添加修改模块搜索路径

    在python交互模式下输入: help('modules') #可以显示出已安装的模块 在python交互模式下输入: import sys sys.path #可以显示出模块搜索路径 增加搜索路径 ...