C++ delete之静态变量问题详解

目录
  • delete释放的指针,再访问
    • 例1
    • 例2
  • static 变量的储存区域
    • 例1
    • 例2 帮助理解
  • 总结

delete释放的指针,再访问

例1

#include <iostream>
using namespace std;
class Box
{
public:
    Box(int,int);
    ~Box();
    void volume();
    static int height;
    int width;
    int length;
};
Box::Box(int wi, int le)
{
    width = wi;
    length = le;
}
Box::~Box(){cout<<"the pointer is released."<<endl;}
void Box::volume()
{
    cout<<height*width*length<<endl;
}
int Box::height = 100;
int main()
{
    Box* p = new Box(10,20);
    delete p;
    cout<<p->height<<endl;
    cout<<Box::height<<endl;
    cout<<"width" <<p->width<<endl;
    cout<<"length "<<p->length<<endl;
    p->volume();
    return 0;
}

//输出:
/*100
100
width 16257288
length 16253120
-1812113408*/

例2

#include <iostream>
using namespace std;
int * func(){
    int * a = new int(10);
    return a;
}
int main(){
    int * p = func();
    cout << *p << endl;//10
    //delete关键字用来释放堆区数据
    delete p;
//    p = new int(5);
    cout << *p << endl;//10
    return 0;
}

//输出
// 10
// 16584968

解释:

访问 delete 之后的内存是一个未定义行为。 未定义行为可能产生任何结果,包括但不限于:产生期望的结果,产生未期望的结果,产生随机的结果,产生无法解释的结果,运行错误,随机的运行时错误,编译错误,等等 ---- 你只是放弃了对这片内存的所有权。获得所有权的人对这片内存做什么(或者说什么都不做)都不关你的事

static 变量的储存区域

https://blog.csdn.net/qq_32900237/article/details/107094377?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_title~default-0.no_search_link&spm=1001.2101.3001.4242参考文章

例1

#include <iostream>
using namespace std;
class Box
{
public:
    Box(int,int);
    ~Box();
    void volume();
    static int height;
    int width;
    int length;
};
Box::Box(int wi, int le)
{
    width = wi;
    length = le;
}
Box::~Box(){cout<<"width: "<< width <<"the pointer is released."<<endl;}
void Box::volume()
{
    cout<<height*width*length<<endl;
}
int Box::height = 100;
int main()
{
    Box* p = new Box(10,20);
    cout<<"point  "<<p<<endl;  //point  0xe91470
    cout<<&(p->height)<<endl;  //0x405004
    cout<<&(p->width)<<endl;   //0xe91470
    cout<<&(p->length)<<endl;  //0xe91474
    cout<<sizeof(p)<<endl;    //4
    cout<<sizeof(*p)<<endl;   //8
    cout<<sizeof(Box)<<endl;  //8
	//delete p;              //width: 10the pointer is released.  用new创建的对象,必须自己用delete回收,不然系统不会帮助回收,出现内存泄漏
    Box a = Box(1,2);
    Box *pa = &a;
    cout<<"point  "<<pa<<endl;  //point  0x61ff00
    cout<<&(pa->height)<<endl;  //0x405004
    cout<<&(pa->width)<<endl;   //0x61fefc
    cout<<&(pa->length)<<endl;  //0x61ff00
    cout<<sizeof(pa)<<endl;     //4
    cout<<sizeof(*pa)<<endl;    //8
    cout<<sizeof(a)<<endl;      //8
    Box b = Box(3,4);
    Box *pb = &b;
    cout<<"point  "<<pb<<endl;  //point  0x61fef4
    cout<<&(pb->height)<<endl;  //0x61fef4
    cout<<&(pb->width)<<endl;   //0x61fef4
    cout<<&(pb->length)<<endl;  //0x61fef8
    cout<<sizeof(pb)<<endl;
    cout<<sizeof(*pb)<<endl;
    return 0;
}
/*
point  0xe91470       新对象的地址
0x405004              静态变量和普通变量地址不连续,是静态变量存在数据段
0xe91470              普通变量存在 开辟的堆上
0xe91474
4                    指针大小
8                    对象所占内存大小
8                    类大小
point  0x61fefc      新对象a的地址
0x405004             静态变量地址不变,静态变量属于整个类
0x61fefc             属于局部变量,普通变量存在 栈空间上
0x61ff00
4
8
8
point  0x61fef4     新对象b的地址, b与a之间相差8个字节
0x405004            静态变量地址不变,静态变量属于整个类
0x61fef4            属于局部变量,普通变量存在 栈空间上,地址连续
0x61fef8
4
8
width: 3the pointer is released.   自动调用析构函数
width: 1the pointer is released.   自动调用析构函数
*/

例2 帮助理解

#include <iostream>
using namespace std;
class Box
{
public:
    Box(int,int);
    ~Box();
    void volume();
    static int height;
    int width;
    int length;
};
Box::Box(int wi, int le)
{
    width = wi;
    length = le;
}
Box::~Box(){cout<<"width: "<< width <<"the pointer is released."<<endl;}
void Box::volume()
{
    cout<<height*width*length<<endl;
}
int Box::height = 100;
int main()
{
    Box* p = new Box(10,20);
    cout<<"point  "<<p<<endl;
    cout<<&(p->height)<<endl;
    cout<<&(p->width)<<endl;
    cout<<&(p->length)<<endl;
    cout<<sizeof(p)<<endl;
    cout<<sizeof(*p)<<endl;
    cout<<sizeof(Box)<<endl;
    // delete p;
    Box* p1 = new Box(30,40);
    cout<<"point  "<<p1<<endl;
    cout<<&(p1->height)<<endl;
    cout<<&(p1->width)<<endl;
    cout<<&(p1->length)<<endl;
    cout<<sizeof(p1)<<endl;
    cout<<sizeof(*p1)<<endl;
    cout<<sizeof(Box)<<endl;
    delete p;
    delete p1;
    Box a = Box(1,2);
    Box *pa = &a;
    cout<<"point  "<<pa<<endl;
    cout<<&(pa->height)<<endl;
    cout<<&(pa->width)<<endl;
    cout<<&(pa->length)<<endl;
    cout<<sizeof(pa)<<endl;
    cout<<sizeof(*pa)<<endl;
    cout<<sizeof(a)<<endl;
    Box b = Box(3,4);
    Box *pb = &b;
    cout<<"point  "<<pb<<endl;
    cout<<&(pb->height)<<endl;
    cout<<&(pb->width)<<endl;
    cout<<&(pb->length)<<endl;
    cout<<sizeof(pb)<<endl;
    cout<<sizeof(*pb)<<endl;
    return 0;
}
/*
point  0x791470
0x405004
0x791470
0x791474
4
8
8
point  0x791108
0x405004
0x791108
0x79110c
4
8
8
width: 10the pointer is released.
width: 30the pointer is released.
point  0x61fef8
0x405004
0x61fef8
0x61fefc
4
8
8
point  0x61fef0
0x405004
0x61fef0
0x61fef4
4
8
width: 3the pointer is released.
width: 1the pointer is released.
*/

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • C++中的局部变量、全局变量、局部静态变量、全局静态变量的区别

    局部变量(Local variables)与 全局变量: 在子程序或代码块中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量. 全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序或代码块. 当全局变量与局部变量同名时:在定义局部变量的子程序内,局部变量起作用:在其它地方全局变量起作用. 全局变量在程序开始运行期间就已经在内存中开辟了内存空间,直到程序结束才会释放这块内存空间. 全局变量要在其他文件中使用,需显示的声明这个变量,使用extern关键字声明(extern int

  • C++中的delete不会将操作数置0

    考虑一下: delete p; // ... delete p; 如果在...部分没有涉及到p 的话,那么第二个"delete p;"将是一个严重的错误,因为C++的实现(译注:原文为a C++ implementation,当指VC++这样的实现了C++标准的具体工具)不能有效地防止这一点(除非通过非正式的预防手段).既然delete 0从定义上来说是无害的,那么一个简单的解决方案就是,不管在什么地方执行了"deletep;",随后都执行"p=0;&qu

  • C++中delete和delete[]的区别

    一直对C++中的delete和delete[]的区别不甚了解,今天遇到了,上网查了一下,得出了结论.做个备份,以免丢失. C++告诉我们在回收用 new 分配的单个对象的内存空间的时候用 delete,回收用 new[] 分配的一组对象的内存空间的时候用 delete[].  关于 new[] 和 delete[],其中又分为两种情况:(1) 为基本数据类型分配和回收空间:(2) 为自定义类型分配和回收空间. 请看下面的程序. #include <iostream>; using namesp

  • C语言自定义类型详解(结构体、枚举、联合体和位段)

    目录 前言 一.结构体 1.结构体类型的声明 2.结构体的自引用 3.结构体变量的定义和初始化 4.结构体内存对齐 5.结构体传参 二.位段 1.位段的定义 2.位段的内存分配 3.位段的应用 三.枚举 1.枚举类型的定义 2.枚举的优点 3.枚举的使用 四.联合体(共用体) 1.联合体的定义 2.联合体的特点 3.联合体的大小计算 总结 前言 一.结构体 1.结构体类型的声明 当我们想要描述一个复杂变量--学生,可以这样声明. ✒️代码展示: struct Stu { char name[20

  • C语言自定义函数的实现

    函数是一段可以重复使用的代码,用来独立地完成某个功能,它可以接收用户传递的数据,也可以不接收.接收用户数据的函数在定义时要指明参数,不接收用户数据的不需要指明,根据这一点可以将函数分为有参函数和无参函数. 将代码段封装成函数的过程叫做函数定义. C语言无参函数的定义 如果函数不接收用户传递的数据,那么定义时可以不带参数.如下所示: dataType functionName(){ //body } dataType 是返回值类型,它可以是C语言中的任意数据类型,例如 int.float.char

  • C++表达式new与delete知识详解

    在C++中,new表达式用于动态创建对象,即在堆(自由存储区)空间上为对象分配内存,而程序员也要小心的使用这些申请来的内存空间,当不再使用时应该调用delete表达式来释放该存储空间并且将指针置零. 本文学习了如何动态创建对象,动态创建的对象与一般对象的区别,动态创建的对象的初始化以及释放动态分配的内存等知识点. C++中分配的内存大致有三类:静态存储区,栈内存和堆内存 其中,静态存储区是在程序编译阶段就已经分配好的,用于全局变量,static变量等:堆栈是比较常用的对象存储方式. new和de

  • C++之类的静态变量

    成员变量 通过对象名能够访问public成员变量 每个对象都可以有只属于自己的成员变量 成员变量不能在对象之间共享 类的静态成员 静态成员变量 存储在 全局数据区 #include<stdio.h> class Test { private: ///静态成员变量访问权限 static int c1; public: static int GetC1() { return c1; } static void SetC1(int i) { c1=i; } void print() //普通成员函数

  • C++静态变量,常量的存储位置你真的了解吗

    目录 引言 C++对内存的划分如何落实在Linux上 自由存储区和堆之间的问题 栈 常量区 静态存储区 静态局部变量 静态局部变量.静态全局变量.全局变量的异同 总结 引言 在动态内存的博客中,我提到: 在Linux 内存管理的博客中,我提到: 尽管都有尽可能完全的描述,并且两者大致意思没有冲突.而之所以令我一直感到略有不同,越看越迷糊的原因是:第一张图讲的其实是C++在概念上对内存的划分,第二张图讲的是Linux对虚拟内存进行的划分. 前者是概念上的,也是C++程序在运行时会切实执行的,而后者

  • C语言自定义类型的保姆级讲解

    前言 在我们日常写代码时,经常会遇到结构体类型的使用,今天带读者了解结构体类型的使用. 一.初始结构体 在了解结构体之前,我们先来了解一下结构体的基础只是,结构体到底是什么? 结构是一些值的集合,这些值称为成员变量.结构的每个成员可以是不同类型的变量. 下面举一个例子: struct tag { menber_list; //成员列表 }variable_list; //变量列表 例如我们使用结构体描述一台电脑 struct computer { int price;//价格 char name

  • C语言菜鸟基础教程之自定义函数

    先动手编写程序: #include <stdio.h> int add(int x, int y) { int z = x + y; return z; } int main() { int a = 1; int b = 2; int c = add(a, b); printf("c = %d\n", c); return 0; } 运行结果: c = 3 程序分析: (1) 函数定义的形式为: 类型 函数名称(类型 形式参数,--) { 函数体 } (2) 对应于咱们的程

  • C语言自定义数据类型的结构体、枚举和联合详解

    结构体基础知识 首先结构体的出现是因为我们使用C语言的基本类型无法满足我们的需求,比如我们要描述一本书,就需要书名,作者,价格,出版社等等一系列的属性,无疑C语言的基本数据类型无法解决,所以就出现了最重要的自定义数据类型,结构体. 首先我们创建一个书的结构体类型来认识一下 struct Book { char name[20]; char author[20]; int price; }; 首先是struct是结构体关键字,用来告诉编译器你这里声明的是一个结构体类型而不是其他的东西,然后是Boo

  • C语言自定义军旗游戏源码

    本文实例为大家分享了C语言自定义军旗游戏的具体代码,供大家参考,具体内容如下 #include <graphics.h> #include <time.h> #define CHESIZE 40 // 棋盘尺寸,不能随意调整 #define RESETX 170 #define RESETY 350 // 重置原点 typedef enum // 要用到的棋子ID { si, jun, shi, lv, tuan, ying, lian, pai, ban, gong, fei,

随机推荐