析构函数

《Effective C++》条款07:为多态基类声明virtual析构函数

落花浮王杯 提交于 2019-12-07 08:02:13
原因:C++明白指出,当派生类对象经由基类指针被删除,而该基类的析构函数是非virtual析构函数,执行的结果是派生类成分未被销毁。 解决方法:将base classes析构函数写为virtual析构函数。 适用范围:该规则只适用于polymorphic(带多态性)的base calsses上。这种base class的设计目的是:通过base class接口处理derived class对象。如果不是为了具备多态性,就不应该声明virtual析构函数。 virtual函数会增大类的内存大小。 来源: CSDN 作者: Simon.Y 链接: https://blog.csdn.net/sinat_38183777/article/details/81228889

条款07:为多态基类声明virtual析构函数

孤街醉人 提交于 2019-12-07 08:01:53
c++面向对象特性其中有多态这个特性,平时使用时用基类指针指向子类对象。当我们进行内存回收的时候调用 delete (基类指针),此实如果基类有一个non-virtual析构函数。这种情况下会导致派生类的对象没有被销毁,只有基类部分会被销毁掉,于是造成一个诡异的“局部销毁”对象。这样的后果会形成资源泄露、数据结构被破坏、而且很难找出原因。 消除这个问题的做法很简单:给base class一个virtual析构函数。此后删除derived class对象就会如你想要的那般,将整个对象都销毁,包括derived class成分。 如果class不含virtual函数,通常表示它并不意图被用做一个base class。当class不企图被当作base class,令其析构函数为virtual往往是个馊主意。因为使用virtual函数会导致对象中有一个虚表指针(vptr),该表存在的目的就是为了实现多态的,但是会占用内存空间。这样做的结果会导致该对象不再和其他语言(如C)内的相同声明有着一样的结构(因为其它语言对应物并没有vptr),因此也不再具有移植性。 请记住 polymorphic(带多态性质的)base class应该声明一个virtual析构函数。如果class带有任何virtual函数,它就应该拥有一个virtual析构函数。 Classes的设计目的如果不是作为base

条款07:为多态基类声明virtual析构函数

笑着哭i 提交于 2019-12-07 07:54:33
有许多种做法可以记录时间,因此,设计一个TimeKeeper base class和一些derived classes作为不同的计时方法,相当合情合理: class TimerKeeper{ public: TimeKeeper(); ~TimeKeeper(); ... }; class AtomicClock:public TimeKeeper{...];//原子钟 class WaterClock:public TimeKeeper{...]; //水钟 class WristWatch:public TimeKeeper{...}; //腕表 当我们指向在程序中使用时间,不想操心时间如何计算等细节,这时候我们可以设计factory(工厂)函数,返回指针指向一个定时对象。Factory函数会"返回一个base class指针,指向新生成的derived class对象": TimeKeeper* getTimeKeeper(); //返回一个指针,指向一个TimeKeeper派生类的动态分配对象 这里存在一个问题,当derived class对象经由一个base class指针被删除,而该base class带着一个non-virtual析构函数,其结果未有定义--实际执行时通常发生的对象的dervied成分没被销毁。 消除这个问题的做法很简单:给base

[翻译] Effective C++, 3rd Edition, Item 8: 防止因为 exceptions(异常)而离开 destructors(析构函数)

谁说胖子不能爱 提交于 2019-12-07 07:44:14
Item 8: 防止因为 exceptions(异常)而离开 destructors(析构函数) 作者: Scott Meyers 译者: fatalerror99 (iTePub's Nirvana) 发布: http://blog.csdn.net/fatalerror99/ C++ 并不禁止从 destructors(析构函数)中引发 exceptions(异常),但是它坚决地阻止这样的实践。至于有什么好的理由,考虑: class Widget { public: ... ~Widget() { ... } // assume this might emit an exception }; void doSomething() { std::vector<Widget> v; ... } // v is automatically destroyed here 当 vector v 被销毁时,它有责任销毁它包含的所有 Widget s。假设 v 中有十个 Widget s,在第一个的析构过程中,抛出一个 exception(异常)。其它 9 个 Widget s 仍然必须被销毁(否则它们持有的所有资源将被泄漏),所以 v 应该调用它们的 destructors(析构函数)。但是假设在这个调用期间,第二个 Widget 的 destructors(析构函数)又抛出一个

Effective C++之 Item 8: 防止因为 exceptions(异常)而离开 destructors(析构函数)

ぐ巨炮叔叔 提交于 2019-12-07 07:43:59
++ 并不禁止从 destructors(析构函数)中引发 exceptions(异常),但是它坚决地阻止这样的实践。至于有什么好的理由,考虑: class Widget { public: ... ~Widget() { ... } // assume this might emit an exception }; void doSomething() { std::vector<Widget> v; ... } // v is automatically destroyed here 当 vector v 被析构时,它有责任析构它包含的所有 Widgets。假设 v 中有十个 Widgets,在第一个的析构过程中,抛出一个 exception(异常)。其它 9 个 Widgets 仍然必须被析构(否则它们持有的所有资源将被泄漏),所以 v 应该调用它们的 destructors(析构函数)。但是假设在这个调用期间,第二个 Widget 的 destructors(析构函数)又抛出一个 exception(异常)。现在同时有两个活动的 exceptions(异常),对于 C++ 来说,这太多了。在非常巧合的条件下产生这样两个同时活动的异常,程序的执行会终止或者引发 undefined behavior(未定义行为)。在本例中,将引发 undefined behavior

一个delete和析构函数引发的coredump

寵の児 提交于 2019-12-07 07:43:44
在一段代码中写了一段类似这样的代码: std::map<sturct* p, iterator> data2itor; std::multimap<uint32_t, struct* p> tim2data; 用tim来定时删除过期数据,正常删除时由data2itor中的second确定在tim2data中的位置从而删除,超时时由time2data确定超时数据,进行删除,数据是一个结构体的指针,在超时的时候要对结构体进行delete,但是在delete的时候在析构函数里做了数据的删除也就是调用了erase,在调用delete之后又调用了一次erase,而导致了一个core的发生,没考虑到析构函数的时候看起来代码非常正常,coredump发生非常诡异,原因就是没考虑到delete会执行一个函数,所以以后在写代码时要考虑到每一行代码可能会做出的奇怪的事情 来源: CSDN 作者: 拂晓 链接: https://blog.csdn.net/freedomcheng/article/details/45114753

Effective C++ 条款08

跟風遠走 提交于 2019-12-07 07:43:12
别让异常逃离析构函数 Prevent exceptions from leaving destructors 析构函数绝对不要抛出异常,如果一个被析构函数调用的函数可能抛出异常,那么析构函数应该处理这个异常并且不能抛出。 这里的理解是,如果一个析构函数抛出异常,会导致当前对象处于未定义状态或者导致程序终止。 转载于:https://www.cnblogs.com/lucy-lizhi/p/7452726.html 来源: CSDN 作者: weixin_30566149 链接: https://blog.csdn.net/weixin_30566149/article/details/98333899

Effective C++——条款8(第2章)

倾然丶 夕夏残阳落幕 提交于 2019-12-07 07:42:57
条款08: 别让异常逃离析构函数 Prevent exception from leving destructors. C++并不禁止析构函数吐出异常,但它不鼓励这样做 .这是有原因的,考虑以下代码: class Widget { public: ... ~Widget() { ... } // 假设这个可能吐出一个异常 }; void doSomething() { std::vector<Widget> v; ... } // v在这里被自动销毁 当vector v被销毁,它有责任销毁其内含的所有Widgets.假设v内含十个Widgets,而在析构第一个元素期间,有个异常被抛出.其他九个Widgets还是应该被销毁(否则它们保存的任何资源都会发生泄漏),因此v应该调用它们各个析构函数.但假设在那些调用期间,第二个Widgets析构函数右抛出异常.现在有两个同时作用的异常,这对C++而言太多了.在两个异常同时存在的情况下, 程序若不是结束执行就是导致不明确行为 .本例中它会导致不明确的行为.使用标准程序库的任何其他容器或TR1的任何容器或甚至array,也会出现相同情况.容器或array并非遇上麻烦的必要条件,只要析构函数吐出异常,即使并非使用容器或arrays,程序也可能过早结束或出现不明确行为. C++不喜欢析构函数吐出异常. 这很容易理解,但如果析构函数必须执行一个动作

Effective C++:条款08

三世轮回 提交于 2019-12-07 07:42:38
Effective C++:条款08:别让异常逃离析构函数 (Prevent exceptions from leaving destructors.) 析构函数绝对不要吐出异常。如果一个被析构函数调用的函数可能抛出异常,析构函数应该捕捉任何异常,然后吞下它们(不传播)或结束程序。 如果客户需要对某个操作函数运行期间抛出的异常做出反应,那么class应该提供一个普通函数(而非在析构函数中)执行该操作。 这节和异常有关,这一块是我不太熟悉的,只能先把自己理解的记录下来。 1 class Widget 2 { 3 public: 4 5   ~Widget() {} //假设这里会吐出一个异常 6 }; 7 8 void doSomething() 9 { 10   std::vector<Widget> v; 11 12 }//v在这里自动销毁 上面的代码中,假设v含有10个Widget,如果在前面几个的析构函数中弹出异常,则程 序会过早结束或者出现不明确行为。 确实不鼓励在析构函数中抛出异常,可是如果程序在析构函数中必须执行一个动作, 而该动作可能会在失败时抛出异常,该怎么办呢?比如下例: 1 class DBConnection 2 { 3 public: 4   static DBConnection create(); 5   void close();//关闭连接

Effective C++读书笔记(6)

旧城冷巷雨未停 提交于 2019-12-07 07:41:58
新年了~忙着东奔西跑3天,是时候回归正常生活了…… 条款08:别让异常逃离析构函数 Prevent exceptions from leavingdestructors C++ 不禁止但不鼓励从析构函数引发异常。考虑: class Widget { public: ... ~Widget() { ... } // 假设这里可能吐出一个异常 }; void doSomething() { std::vector<Widget> v; ... } // v在这里被自动销毁 当 vector v 被析构时,它有责任析构它包含的所有 Widgets。但假设在那些调用期间,先后有两个Widgets抛出异常,对于 C++ 来说,这太多了。在两个异常同时存在的情况下,程序若不是结束执行就是导致不明确行为。在本例中将导致不明确行为,使用标准库的任何其他容器(如list,set)或TR1的任何容器甚至array,也会出现相同情况。C++ 不喜欢析构函数吐出异常。 如果你的析构函数需要执行一个可能失败而抛出一个异常的操作,该怎么办呢?假设使用一个class负责数据库连接,为了确保客户不会忘记在 DBconnection对象上调用 close(),一个合理的想法是创建一个用来管理DBConnection资源的类,并在其析构函数中调用close: class DBConn { //