首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么 this 指针地址与析构函数中的预期不同(c ++)

在C++中,this指针是一个隐含的指针,它指向当前对象的地址。在类的成员函数中,this指针可以用来访问当前对象的成员变量和成员函数。

然而,在析构函数中,this指针的行为与其他成员函数不同。析构函数是在对象销毁时自动调用的特殊成员函数,用于释放对象所占用的资源。由于对象即将被销毁,this指针在析构函数中的行为可能与预期不同。

具体来说,this指针在析构函数中可能指向已经被释放的内存区域。这是因为在对象销毁时,首先会调用析构函数,然后才会释放对象所占用的内存。因此,在析构函数中使用this指针可能导致访问已经无效的内存,从而引发未定义的行为。

为了避免这种情况,通常建议在析构函数中不要使用this指针。如果需要在析构函数中访问对象的成员变量或调用成员函数,可以直接使用成员变量或成员函数的名称,而无需通过this指针。

总结起来,this指针地址与析构函数中的预期不同是因为在析构函数中,对象即将被销毁,this指针可能指向已经被释放的内存区域。因此,在析构函数中应避免使用this指针来访问对象的成员。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

C++类构造函数函数

C++每个类都有其构造函数,它们负责对象创建和对象清理和回收,即使我们不写这两个,编译器也会默认为我们提供这些构造函数。...下面仍然是通过反汇编方式来说明C++构造和函数是如何工作。...编译器是否真的会默认提供构造函数 在一般讲解C++书籍中都会提及到当我们不为类提供任何构造函数时编译器会默认提供这样六种成员函数:不带参构造,拷贝构造,“=”重载函数函数,以及带const...由于默认拷贝构造是进行简单内存拷贝,所以当类成员中有指针变量时尽量自己定义拷贝构造,进行深拷贝,否则在以后进行时会崩溃。...8] 当类作为返回值返回时,如果定义了一个变量来接收这个返回值,那么在调用函数时会首先保存这个值,然后直接复制到这个内存,但是接着执行类函数函数定义类对象,接受返回值得这块内存一直等到它所在语句块结束才调用

1.6K10

javafinalize()方法C++函数

finalize()方法函数存在天然差别,这种差别源于语言本身机制不同。 在C++,对象是可以在栈上分配,也可以在堆上分配。...所以在java,对象内存在哪个时刻回收,取决于垃圾回收器何时运行。因此,C++java,对无用对象回收时间是不同。...C++函数用来做一些必要工作,例如释放掉指针成员所指向对象所占内存,因为C++没有java垃圾回收器,所有new出来对象,都要显式地delete掉,避免内存泄漏。...《Effective C++》中提及,基类需要将函数声明为virtual函数,这是为了可以通过子类对象指针正确地释放掉基类资源。...总的来说,在C++函数和资源释放息息相关,能不能正确处理函数,关乎能否正确回收对象内存资源。

1.6K50

javafinalize( )方法C++函数

一、函数作用         函数(destructor) 构造函数相反,当对象结束其生命周期时(例如对象所在函数已调用完毕),系统自动执行函数。...finalize()方法函数存在天然差别,这种差别源于语言本身机制不同。 1、对无用对象回收时间不同C++,对象是可以在栈上分配,也可以在堆上分配。...所以在java,对象内存在哪个时刻回收,取决于垃圾回收器何时运行。因此,C++java,对无用对象回收时间是不同。...C++函数用来做一些必要工作,例如释放掉指针成员所指向对象所占内存,因为C++没有java垃圾回收器,所有new出来对象,都要显式地delete掉,避免内存泄漏。...《Effective C++》中提及,基类需要将函数声明为virtual函数,这是为了可以通过子类对象指针正确地释放掉基类资源。

1.1K40

C++:39---继承构造函数函数关系

继承构造父类构造函数相类似: 如果类定义对象没有构造函数,则该类初始化时不需要构造该对象构造函数 如果类定义对象有构造函数,则该类初始化自己构造函数时,要先初始化该对象构造函数 总结...{ b_data = data; } ~B() {} }; 三、继承父、子类构造函数函数执行顺序 构造函数执行顺序: 第一步:先构造父类构造函数 第二步:如果类定义了其他类对象,再初始化其他类构造函数...第三步:最后初始化自己构造函数 函数执行顺序: 构造函数执行顺序相反 第一步:先执行自己函数 第二步:如果类定义了其他类对象,再执行其他类函数 第三步:最后执行父类函数...但子对象必须在成员初始化列表进行初始化 四、单继承构造函数函数执行顺序 下面代码: 构造函数执行顺序为:2-1-3 函数执行顺序为:6-4-5 //单继承 class M { int m_data...、函数执行顺序 下面代码: 构造函数执行顺序为:1-2-3 函数执行顺序为:6-5-4 //多继承 class A { int a_data; public: A(int data) { a_data

99420

C++ 构造函数函数调用虚函数注意事项

但是为什么在构造函数调用虚函数,实际上没有发生动态联编呢? 第一个原因,在概念上,构造函数工作是为对象进行初始化。在构造函数完成之前,被构造对象被认为“未完全生成”。...在Visual C++,包含虚函数类对象指针被安排在对象起始地址处,并且虚函数表(vtable)地址是由构造函数写入虚指针。...同样,在函数调用虚函数函数入口地址也是在编译时静态决定。也就是说,实现是实调用而非虚调用。 考察如下例子。...b退出作用域时,会先调用类B函数,然后调用类A函数,在函数~A(),调用了虚函数show()。...从概念上说,函数是用来销毁一个对象,在销毁一个对象时,先调用该对象所属类函数,然后再调用其基类函数,所以,在调用基类函数时,派生类对象“善后”工作已经完成了,这个时候再调用在派生类定义函数版本已经没有意义了

92310

C++11 在函数执行lambda表达式(std::function)捕获this指针陷阱

[=] { fun(12345); }; [&] { fun(12345); }; 顺序 然后我想到了C++ 顺序问题,按照C++标准,C++对象顺序构造顺序完全相反...因为问题原因不是lambda表达捕获this指针不对,而是在基类函数,lambda表达式所捕获this指针所指向子类对象部分数据已经无效,不可引用了。...最后一个问题:为什么gcc和vs2015下代码表现不同?...我同样用前面在std::function函数加断点方式在eclipse+gcc环境下做了测试,测试结果表明gcc也是按C++标准顺序执行对象,但不同是gcc在构造下面这个lambda表达式时...因为这时子类类成员变量已经被了,但是子类指针类型、基本数据类型变量因为不存在问题所以还是可以用

1.5K10

C++构造函数函数抛出异常注意事项

从语法上来说,构造函数函数都可以抛出异常。但从逻辑上和风险控制上,构造函数函数尽量不要抛出异常,万不得已,一定要注意防止资源泄露。在函数抛出异常还要注意栈展开带来程序崩溃。...由于在类B构造函数抛出了异常,而此异常并未在构造函数中被捕捉,所以导致类B构造函数执行中断,对象b并未构造完成。在类B构造函数“回滚”过程c函数和类A函数相继被调用。...最后,由于b并没有被成功构造,所以main()函数结束时,并不会调用b函数,也就很容易造成内存泄露。 2.函数抛出异常 在函数是可以抛出异常,但是这样做很危险,请尽量不要这要做。...那么如果无法保证在函数不发生异常, 该怎么办? 其实还是有很好办法来解决。那就是把异常完全封装在函数内部,决不让异常抛出函数之外。这是一种非常简单,也非常有效方法。...} } 在面对函数抛出异常时,程序猿要注意以下几点: (1)C++函数执行不应该抛出异常; (2)假如函数抛出了异常,那么你系统将变得非常危险,也许很长时间什么错误也不会发生

2K10

C++基础——C++面向对象之类、对象继承基础总结(类和对象概念、构造函数函数、this指针、继承)

构造函数特点: 1)构造函数必须类名同名; 2)可以重载; 3)没有返回类型,即使是 void 也不行。         函数构造函数相反, 在对象结束其生命周期时系统自动执行函数。...People类,然后自己写一个构造函数函数,在函数及main函数打印信息。...1.3 this指针         每个对象都拥有一个 this 指针, this 指针记录对象内存地址,在 C++, this 指针是指向类自身数据指针, 简单来说就是指向当前类的当前实例对象...; 3)this 指针会因编译器不同而有不同放置位置。...+类和对象基本概念,给出了构造函数函数区别,并总结了this指针使用方法,有了以上基础后,进一步总结了C++语言三大特征之一继承基本概念,并结合实例演示了继承使用方法。

80150

C++】继承 ⑦ ( 继承对象模型分析 | 继承构造函数函数 )

C : public B { public: int z; }; 分别定义上述 3 个类对象 , A objA; B objB; C objC; 2、基类派生类内存模型 上述 3 个对象内存模型如下...system("pause"); return 0; } 二、继承构造函数函数 ---- 1、子类构造函数函数调用顺序 继承构造函数函数 : 子类构造 : 子类对象 进行..., 再调用 子类 构造函数 , 构造 子类 自己定义成员 ; 子类 : 子类对象 进行 时 , 需要调用 父类 函数 对 继承自父类 成员变量 进行 操作 ; 函数调...用顺序如下 : 时 , 先 调用 子类 函数 , 子类 自己成员 ; 然后 , 再调用 父类 函数 , 继承自父类成员 ; 2、子类构造函数参数列表 如果...C 函数调用 B 函数调用 A 函数调用

20840

从零开始学C++之虚函数多态(一):虚函数指针、虚函数、object slicing函数C++对象模型图

函数覆盖隐藏可以参考这里。 三、几道c++面试题 1....所以结果是分别调用是Base::doPrint和Derived::doPrint2。 四、虚函数 何时需要虚函数?...当你可能通过基类指针删除派生类对象时 如果你打算允许其他人通过基类指针调用对象函数(通过delete这样做是正常),并且被派生类对象是有重要函数需要执行,就需要让基类函数作为虚函数...即通过delete 基类指针删除了派生类对象(执行派生类函数),此时就好像delete 派生类指针 效果一样。如果基类函数没有声明为virtual, 此时只会输出~Base。...六、C++对象模型图 Rectangle 继承自Shape类,Shape函数为虚函数,draw为纯虚函数 ? ?

1.1K00

C++继承对象模型继承构造和顺序

继承对象模型 问题:从父类继承过来成员,哪些属于子类对象?...,只是由编译器给隐藏后访问不到 继承构造和顺序 子类继承父类后,当创建子类对象,也会调用父类构造函数 问题:父类和子类构造和顺序是谁先谁后?...<< endl; } ~Son() { cout << "Son函数!"...<< endl; } }; void test01() { //继承 先调用父类构造函数,再调用子类构造函数顺序构造相反 Son s; } int main() { test01...(); system("pause"); return 0; } 速记:构造时现有父亲后又儿子,顺序相反(白发送黑发) 总结:继承 先调用父类构造函数,再调用子类构造函数顺序构造相反

57420

C++】从入门到精通第二弹——类构造函数

写在最前面的话 ——构造函数函数是两个特殊成员函数,都没有返回值,构造函数名和类名相同,函数名只是在类名前加上 ~ 构造函数主要用来在创建对象时给对象数据成员赋值,主要目的是初始化对象..., 函数功能与构造函数正好相反,函数是用来释放对象,再删出对象前,对对象进行清理工作。...函数不能发生重载 不管是构造函数还是函数都不能使用return语句,没有返回值 在不同环境下构造函数函数调用规则如下: 自动变量作用域是某个模块,当此模块被激活时,调用构造函数,...全局变量在进入main函数之前调用构造函数,在程序终止时调用函数。 动态分配对象在使用new为对象分配内存时调用构造函数,使用delete删除对象时调用函数。...临时变量是编译器为支持计算自动产生,临时变量生存期开始和结束点会调用构造函数函数

11840

C++:51---继承构造函数函数、拷贝控制一系列规则

一、继承构造函数 根据构造函数执行流程我们知道: 派生类定义时,先执行基类构造函数,再执行派生类构造函数 拷贝构造函数上面是相同原理 二、继承函数 根据函数执行流程我们知道:...规则如下: 如果基类默认构造函数、拷贝构造函数、拷贝赋值运算符、或函数是被删除或者是不可访问,则派生类对应成员将是删除,原因是编译器不能使用基类成员来执行派生类对象属于基类部分操作...} }; 五、特别注意:在构造函数函数调用虚函数 根据构造函数函数我们知道: 派生类构造时,先构造基类部分,然后再构造派生类部分 派生类时,先派生类部分,然后再基类部分 因此...: 在基类构造函数执行时候,派生类部分是未定义状态 在基类函数执行时候,派生类部分已经被释放了 所以在基类构造函数函数调用虚函数是不建议,因为: 虚函数在执行时候可能会调用到属于派生类成员...,而此时派生类可能还未构造/或者已经被释放了,因此程序可能会崩溃 所以建议: 如果构造函数函数调用了某个虚函数,则应该执行构造函数函数所属类型相同函数版本(同属于一个类) 六、继承/重用基类构造函数

1.3K30

C++对象初始化和清理之构造函数函数分析实例(一)

对象初始化和清理 生活我们买电子产品都基本会有出厂设置,在某一天我们不用时候也会删除一些自己信息数据保证安全 C++面向对象来源于生活,每个对象也都会有初始设置以及 对象销毁前清理数据设置...构造函数函数 对象初始化和清理也是两个非常重要安全问题 ​ 一个对象或者变量没有初始状态,对其使用后果是未知 ​ 同样使用完一个对象或变量,没有及时清理,也会造成一定安全问题 c++利用了构造函数函数解决上述问题...~类名(){} 函数,没有返回值也不写void 函数名称类名相同,在名称前加上符号 ~ 函数不可以有参数,因此不可以发生重载 程序在对象销毁前会自动调用,无须手动调用,而且只会调用一次...; system("pause"); return 0; } 注意:在main函数,只有构造没有,因为程序在system(“pause”)处暂停了程序,所以不会调用函数,当main函数运行完成前会自动调用函数...所以运行dowork2()后会先是调用构造再调用拷贝构造return一个p,最后是p1再是test03()p。 用值方式返回相当于拷贝构造。

60120

C++多态

协变(基类派生类虚函数返回值类型不同) 三同,返回值可以不同,但是要求返回值必须是一个父子类关系指针或者引用。...(基类派生类函数名字不同) 如果基类函数为虚函数,此时派生类函数只要定义,无论是否加virtual关键字,都与基类函数构成重写,虽然基类派生类函数名字不同。...在上面的代码例子,只有派生类Student函数重写了Person函数,delete对象调用函数,才能构成多态,才能保证p1和p2指向对象正确调用函数。...接着是虚表存在,又称虚函数表,虚函数表本质上是一个函数指针数组,存放是类函数地址。因此,指向虚函数是虚表指针,在32位平台下,指针大小是4,因此一共是12个字节。...在调用重写函数时候,如果指向是派生类对象,那么就必须从这个派生类虚表拿到这个虚函数地址。 ②为什么要基类对象指针或引用去调用虚函数: 首先,虚函数必须写在基类

82820

C++ 多态实现机制

需要注意一点是, 派生类函数表和基类结构是一致, 其中函数和 eat() 是自己, bark() 沿用了 Animal (函数编译器自动制造一个)....虚拟函数 (Virtual destructors) 关于函数, 若类存在虚函数, 则必须将该类函数也设为 virtual, 否则会有麻烦, 因为如果不是 virtual, 在时发生是静态绑定..., 派生类就被丢掉了....重写 (Overridding) C++ , Overidding 重定义了 virtual function 函数体, 发生 overriding 之后, 若要调用基类同名 virtual...通过函数指针调用 virtual function 尝试 既然已经能够得到虚函数地址, 那么自然想要尝试用函数指针方式来调用, 但是这并没有想象那么简单, 以下内容来自本人尝试, 非常感谢

66440

CC++面试常问题集(2)

三,赋值运算符重载函数  赋值运算符重载函数也不会被子类继承,只是在子类赋值运算符重载函数中会调用父类赋值运算符重载函数。 7、基类函数为什么要用virtual虚函数?...C++基类采用virtual虚函数是为了防止内存泄漏 具体地说,如果派生类申请了内存空间,并在其函数对这些内存空间进行释放。...假设基类采用是非虚函数,当删除基类指针指向派生类对象时就不会触发动态绑定,因而只会调用基类函数,而不会调用派生类函数。...那么在这种情况下,派生类申请空间就得不到释放从而产生内存泄漏。所以,为了防止这种情况发生,C++基类函数应采用virtual虚函数。...它们都可用于申请动态内存和释放内存; new/delete会调用对象构造/函数, 而malloc/free只会分配/释放内存; mallocfree是C++/C语言标准库函数,new/delete

1.1K10
领券