C++ C++;在析构函数中序列化是个坏主意吗?如果是,为什么?

C++ C++;在析构函数中序列化是个坏主意吗?如果是,为什么?,c++,serialization,destructor,boost-serialization,C++,Serialization,Destructor,Boost Serialization,在类的~dtor中调用save函数(ala boost serialize)会产生什么负面/未定义的行为?这是个坏主意 ,IO操作很可能会抛出,因为IO成功与否基本上是您无法控制的 至少对我来说,这是非常不直观的 A.一方面,它确保该类型的每个对象都将被序列化(除非析构函数有防止这种情况发生的检查) B析构函数有一个非常明确的目的,即清理,存储数据基本上与清理相反 我只想再强调一点,通过在析构函数中序列化你能得到什么 您知道,如果使用RAII,即使出现异常,序列化也会运行。但这并不是一个很大的

在类的~dtor中调用save函数(ala boost serialize)会产生什么负面/未定义的行为?

这是个坏主意

  • ,IO操作很可能会抛出,因为IO成功与否基本上是您无法控制的
  • 至少对我来说,这是非常不直观的
    A.一方面,它确保该类型的每个对象都将被序列化(除非析构函数有防止这种情况发生的检查)
    B析构函数有一个非常明确的目的,即清理,存储数据基本上与清理相反 我只想再强调一点,通过在析构函数中序列化你能得到什么



    您知道,如果使用RAII,即使出现异常,序列化也会运行。但这并不是一个很大的好处,因为即使析构函数将运行,您也不能保证序列化将在抛出后运行(至少在本例中是这样)。此外,您还失去了许多正确处理故障的能力。

    问题在于
    boost serialize
    可能引发异常。这意味着,如果调用析构函数是因为异常正在传播,并在堆栈展开时清理堆栈,那么如果对象的析构函数引发另一个异常,则应用程序将终止


    总之,您总是希望一次只传播一个异常。如果您最终得到多个异常,那么您的应用程序将关闭,这将违背异常的目的。

    不,这不是一个坏主意,但也不是一个非常好的主意! 但有时这样做是正确的


    只要您保护析构函数不抛出异常,就没有什么可以阻止它。

    您有两个顾虑,其中一个是另一个的后果:

    1) 您不应该允许任何异常转义析构函数。如果执行此操作,并且在堆栈展开过程中调用析构函数,则运行时将
    终止()
    您的程序。这不是未定义的行为,但它是相当消极的

    因此(当然也因为析构函数不返回值):

    2) 对于析构函数来说,没有合理的方法来表示成功或失败(“合理”的意思是,如果不建立某种独立的错误报告系统)。由于类的用户可能想知道是否发生了保存,最好使用一个合理的API来进行,这意味着析构函数只能在“尽力”的基础上保存数据。如果保存失败,那么对象仍然会被销毁,因此其数据可能会丢失

    对于这种情况有一种策略,例如由文件流使用。它的工作原理如下:

    • 具有保存数据的
      flush()
      (或者在您的情况下是
      save()
      )函数
    • 如果对象尚未保存/刷新,则从析构函数调用此函数(或者更可能:无条件调用它,但让函数本身知道是否需要执行任何实际工作)。对于文件流,这是通过
      close()
      实现的。捕获它可以抛出的任何异常并忽略任何错误
    这样,需要知道保存是否成功的用户可以调用
    save()。不在乎的用户(或者在抛出异常并作为堆栈展开的一部分销毁对象的情况下,如果可能的话,不介意它成功的用户)可以让析构函数尝试

    也就是说,您的析构函数可以尝试做一些可能失败的事情,作为最后的努力,但您还应该为用户提供一种“正确”完成同样事情的方法,以告知他们成功或失败


    是的,这并不意味着在不刷新流并检查流状态是否失败的情况下使用流是不“正确”使用它们的,因为您无法知道数据是否被写入。但是在某些情况下,这已经足够好了,在同样的情况下,您的类保存在其析构函数中也可能足够好。

    @Mehrdad my bad+1来弥补它您是在尝试序列化正在销毁的对象还是其他什么BTW@aaronman哦,不,只是出于好奇问。对我来说,这似乎是一个理想的保存时间,就在对象即将死亡的时候。好吧,因为如果不是真正的对象被破坏,你可能可以设置一个标志或一些东西来提醒另一个函数进行序列化(你不想直接调用该函数),实际上这是一个非常糟糕的主意,阅读其他答案here@aaronman当前位置到目前为止,你是唯一一个说情况不好的人。到目前为止,另一个答案并没有说明它是好是坏。我认为你错了。随便你,我的凯撒回答绝对不建议这样做it@aaronman当前位置推荐和声明这是一个坏主意是两件完全不同的事情。我也不推荐这样做,但有时这是唯一正确的做法。如果你没有直截了当地说:这是个坏主意,我会投赞成票的。@Edwin我认为这是个坏主意,即使你处理了投掷问题,它最终还是非常不直观地存储在析构函数的文件中。或者你的直觉是错误的(直觉大多是,除非你是个女人,哈哈)我不认为直觉是错误的,但它并没有涵盖所有的情况。正如我在我的回答中提到的:标准流在析构函数中保存数据,因此C++的直觉应该允许这样做。直觉是正确的,你不应该把析构函数的目的保存到数据中。当它被摧毁时,这是它最后一次完成它的机会。@SteveJessop这个OP已经指出这是一个假设的情况,所以在没有事情进行的情况下,很难就解决这个问题的正确方法形成意见,我打赌如果他举个例子,会有更好的方法来处理