最近面试的时候被问到一个问题是,在C++中,能否在类的成员函数中调用delete this,后来网上查了一下资料,关于这个问题说得比较好的有http://blog.sina.com.cn/s/blog_4b4cf2af0100ywgv.html

但是自己尝试了一下,还是有点区别的。

我写了如下代码:

class A {
public:
A() {
member = ;
}
~A() {
member = ;
}
int test() {
cout << member << endl;
cout << this << endl;
delete this;
cout << this << endl;
cout << member << endl;
}
private:
int member;
}; int main(){
A a;
a.test();
a.test();return ;
}

这份代码编译和运行都没有问题,在test中,打印了一个1,然后打印this的地址,delete this之后,再打印this的地址,发现没有变化,再打印member的值,发现变成了0

1. 在调用delete的时候,C++会帮我们调用这个对象的析构函数,因此member在析构函数中被置为了0

2. 调用delete只是告诉系统我们不需要这个对象的内存空间了,请求释放它,但并不会主动帮我们把这个指针置为null,它依然指向原来的内存地址

3 有趣的是,参考的博客说,在delete this之后,会释放掉类的对象的内存空间,因此如果不在delete this之后调用成员函数,那就没有任何问题,如果调用了成员函数,那就会出错,因为已经没有这个对象的成员了。但是我发现其实还是可以的。之后我又尝试了另外一种写法,代码如下:

class A {
public:
A() {
member = ;
}
~A() {
member = ;
}
int test() {
cout << member << endl;
cout << this << endl;
delete this;
cout << this << endl;
cout << member << endl;
}
private:
int member;
}; int main(){
A *a = new A();
a->test();
a->test();
return ;
}

这次我使用的是一个类的指针对象,然后为这个指针new一个新的对象,然后再次调用test函数,编译过程没有任何问题,但是在运行的时候会出现运行出错,并且在调用delete this之后,打印出来的member都是乱值。因此在类的成员函数中调用delete this,只是当这个对象是由一个指针new出来的对象有效果,并且会出现说delete this之后对象被释放,在delete this之后调用成员内容会出现不可知的错误。

那为什么会出现这两种不一样的结果呢?我个人猜测是因为,当我们是用A a = A()这样产生一个局部对象的时候,由于这个对象是被压入我们的函数栈当中,因此当你delete这个对象的指针,它也还是会存在这个函数栈当中,只有但函数栈回收的时候才会回收这个对象,而对于A *a = new A()这样的情况,a指针对应的对象是被分配到堆当中的,当我们delete的时候,系统就可以马上回收这个堆的内容并可能对堆的内容分布做一些优化和调整,这个时候对象对应的内容也就不存在了。

我再测试了一小段代码:

class A {
public:
A() {
member = ;
}
~A() {
member = ;
}
int test() {
cout << member << endl;
cout << this << endl;
delete this;
cout << this << endl;
cout << member << endl;
}
private:
int member;
int member2;
}; int main(){
A a = A();
A *ptr = &a;
delete ptr;
ptr->test();
return ;
}

用一个指针绑定a对象,a是一个局部的对象,然后delete这个指针的内容,然后用ptr去调用a的成员函数,这种情况也是编译和运行完全没有问题。

在类的成员函数中调用delete this的更多相关文章

  1. 在成员函数中调用虚函数(关于多态的注意事项)------新标准c++程序设计

    类的成员函数之间可以互相调用.在成员函数(静态成员函数.构造函数和析构函数除外)中调用其他虚成员函数的语句是多态的.例如: #include<iostream> using namespa ...

  2. C++类的成员函数使用的一些小总结

    From: http://blog.csdn.net/xiayefanxing/article/details/7607506 这一阵做项目代码开发的时候,用到了在一个C++文件中使用另一个类的成员函 ...

  3. C++ 11 线程调用类的成员函数解决办法

    在C++中,_beginthreadex 创建线程是很麻烦的.要求入口函数必须是类的静态函数. 通常,可以采用thunk,或者模板来实现. 因C++ 11中引入了 std::async ,可以很好的解 ...

  4. 深入理解类成员函数的调用规则(理解成员函数的内存为什么不会反映在sizeof运算符上、类的静态绑定与动态绑定、虚函数表)

    本文转载自:http://blog.51cto.com/9291927/2148695 总结: 一.成员函数的内存为什么不会反映在sizeof运算符上?             成员函数可以被看作是类 ...

  5. 空类指针为什么可以调用类的成员函数 以及 A(){}和A();

    1. 代码及问题 #include <iostream> using namespace std; class A { public: A() {} //A *p = new A()时:此 ...

  6. VB6/VBA中跟踪鼠标移出窗体控件事件(类模块成员函数指针CHooker类应用)

    一.关于起因 前几天发了一篇博文,是关于获取VB类模块成员函数指针的内容(http://www.cnblogs.com/alexywt/p/5880993.html):今天我就发一下我的应用实例. V ...

  7. 线程的函数中调用MFC对话框类的变量

    线程的函数中调用MFC对话框类的变量多线程传输文件的对话框 现在想要在对话框上添加一个进度条 为进度条映射变量m_progress这就需要在传输一段文件后就更新m_progress的值使进度条前进 也 ...

  8. C++点滴----关于类常成员函数

    关于C++中,类的常成员函数 声明样式为:   返回类型 <类标识符::>函数名称(参数表) const 一些说明: 1.const是函数声明的一部分,在函数的实现部分也需要加上const ...

  9. (转)c++类的成员函数存储方式(是否属于类的对象)---一道面试题引发的思考

    昨天去面试一家公司,面试题中有一个题,自己没弄清楚,先记录如下: class D { public: void printA() { cout<<"printA"< ...

随机推荐

  1. 可能是最好的SQL入门教程

    个人博客:这可能是最好的SQL入门教程

  2. 用golang 实现一个代理池

    背景 写爬虫的时候总会遇到爬取速度过快而被封IP的情况,这个时候就需要使用代理了.在https://github.com/henson/ProxyPool 的启发下,决定自己实现一个代理池.项目已经开 ...

  3. Maven-04: 三套生命周期

    Maven的生命周期不是一个整体,而是拥有三套相互独立的生命周期,它们分别是clean,default和site. clean生命周期的目的是清理项目. default生命周期的目的是构建项目. si ...

  4. day1 安装jdk8环境及第一个java程序

    安装jdk8 第一步:下载jdk安装包,我们这里下载orical官网的jdk8版本.

  5. execCommand的复制

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  6. spring boot jsp页面

    相关内容访问: http://www.cnblogs.com/zj0208/p/5985698.html

  7. linux --> Linux 的启动流程

    Linux 的启动流程 操作系统接管硬件以后发生的事情,也就是操作系统的启动流程. 因为在BIOS阶段,计算机的行为基本上被写死了,程序员可以做的事情并不多:但一旦进入操作系统,程序员几乎可以定制所有 ...

  8. java排序算法(一):概述

    java排序算法(一)概述 排序是程序开发中一种非常常见的操作,对一组任意的数据元素(活记录)经过排序操作后,就可以把它们变成一组按关键字排序的一组有序序列 对一个排序的算法来说,一般从下面三个方面来 ...

  9. centos 7.0远程登录

    http://blog.csdn.net/e1219092641/article/details/79586476 linux在虚拟机上操作也是有许多不便之处的,但是远程登录的使用可以使操作简单不少, ...

  10. JavaScript简史

    JavaScript诞生于1995年. 当时的web正在日益兴起,人们对客户端语言的需求也越来越强烈.当时走在技术革新最前沿的Netscape公司决定开发一种客户端语言,用来处理简单的输入验证. 当时 ...