我有一个C ++类(在一个dll项目中),其成员变量是boost :: shared_ptrs到其他类的对象。将它们分配到类构造函数中还是有一个单独的init()函数可以做到这一点更好。
我假设指向T内部指针的默认值boost :: shared_ptr为NULL。所以如果我在构造函数中什么也不做,那么在调用Init()函数之前,boost :: shared_ptr的get()会返回NULL。
此外,如果在一个赋值语句中存在new的内存分配问题,我应该捕获异常(在Init中)还是告诉调用者这个Init()捕获该异常? boost :: shared_ptr a(new T);
是否有标准方法来模拟单元测试中的内存分配异常?并看到所有对象都已正确解除分配
答案 0 :(得分:2)
我有一个C ++类(在一个dll项目中),其成员变量是boost :: shared_ptrs到其他类的对象。将它们分配到类构造函数中还是有一个单独的init()函数可以做到这一点更好。
在构造函数中执行所有操作通常更好 使用一个名为afterwords的init()函数意味着该对象在构造后无效,因此您需要保留一个状态标志以指示是否已调用init()并在调用任何公共方法时检查该标志并执行适合未初始化对象的东西
我假设指向T内部指针的默认值boost :: shared_ptr为NULL。所以如果我在构造函数中什么也不做,那么在调用Init()函数之前,boost :: shared_ptr的get()会返回NULL。
是:shared_ptr的默认构造函数会将其初始化为NULL。
此外,如果在一个赋值语句中存在new的内存分配问题,我应该捕获异常(在Init中)还是告诉调用者这个Init()捕获该异常? boost :: shared_ptr a(new T);
如果你有一个构造函数:那么所有构造的成员都将被正确销毁(通过析构函数),而不会触及单元化对象,并且当前对象的内存将被释放,就像从未分配一样(另一个好处)使用初始化列表的原因)。
如果使用init():那么必须捕获异常才能正确清理对象并释放内存。取决于您可以在init内部执行此操作的对象的复杂程度(但很难正确执行)或调用者必须执行此操作。之后你应该像从构造函数中抛出异常一样(这取决于用法)。
是否有标准方法来模拟单元测试中的内存分配异常?并看到所有对象都已正确解除分配
您可以使用工厂对象来分配对象 您将工厂对象传递给构造函数。如果要在构造期间模拟异常,只需传递一个生成相应异常的模拟工厂。
答案 1 :(得分:1)
使用初始化列表进行成员分配。他们是首选(有时是唯一的方法)。
如果在对象创建过程中出现问题,请抛出异常并进行纾困。或者,您需要维护一个valid
标志,每次调用成员函数时都必须检查该标志,以检查正在使用的对象是否有效。
您始终可以捕获异常并报告它们。如果一个deallcation失败,你理想情况下不应该抛出异常,而是在dtor中处理它,报告并继续。
答案 2 :(得分:1)
关于第一个问题,理想情况下应使用初始化列表来确保指针有效。不执行此操作意味着您可能必须在使用之前始终检查指针是否有效;特别是如果你把它留给调用代码来调用init()
另一方面,如果只能通过调用纯虚拟设置来设置,则可能无法执行此操作,在这种情况下,您必须使用init()
方法。
在初始化时,我认为你可以抓住并重新抛出或者根本不抓住。无论哪种方式,我认为调用者可以捕获内存分配异常。
我可以看到为什么你想在你的一个对象上调用init()
时尝试测试内存分配异常。这里的方法可能是替换始终抛出init()
我不明白为什么你要检查共享指针的释放(原始指针,也许)当然,共享指针的一点是,你可以引用共享指针,根据定义,分享它,以便它不会被破坏。
也许您可以检查引用计数或设置您的指向对象并(在销毁时)清除您的测试可以监视的信号量。我不知何故错过了这一点吗?