2009-10-19 133 views
14

我遇到很多次代码,其中在构造函数和析构函数中调用std :: vector类成员的std :: vector :: clear()。std :: vector :: clear()在构造函数和析构函数中

我不明白为什么它的需要:

  1. 构造 - STD型的类成员:: vector的默认是空的,所以没有必要要求明确()。
  2. 析构函数 - 类型std :: vector的类成员将作为包含它的对象的标准销毁的一部分被销毁。作为矢量销毁的一部分,所有值对象包含在其中将被销毁(如果堆分配了指向内存的指针,则应该将它们手动删除),因此再次不需要调用clear()。

我错过了什么吗?

回答

16

从事物的声音来看,编写代码的人就是那些错过了某些东西的人。在ctor或者dtor中调用clear()将唯一有意义的时间是其他代码的中间值。例如,ctor可能读入一些数据,处理它,然后读入更多数据。在这种情况下,读取数据时使用单个容器可能会更快,并且每次都清除它,而不是每次迭代创建一个新容器。

5

不,你说得对。除非是在构造函数中的一些额外的业务(或基类的构造函数)是需要的,但机会是非常低的...

后来编辑

在析构函数的情况下,一个的我看到的最常见的错误是有些人认为清除方法也会调用指针(向量)向量的删除,当然,情况并非如此

22

不,您不会错过任何东西。我怀疑这是(无害的)巫术编程,有点像在释放它之后将指针设置为null,或者在GUI代码中随机调用repaint/revalidate。程序员记得它过去帮助过某种错误,现在不必要地增加它“以防万一”。谁知道,也许会有帮助。巫毒。

+2

不错的术语,'巫术编程':) – xtofl 2009-10-19 20:51:49

+7

设置一个指针为null不是巫术,它对调试有很大的帮助。也可以防止你删除同一个指针两次,但没有人会这样做 - 对吧? – 2009-10-19 21:01:25

+12

如果有的话,你想知道你删除了同一个指针两次。最好是大声地失败(并且了解它)而不是意外地成功(掩盖一个会回来咬你的bug) – 2009-10-19 21:04:17

7
  1. 这是COMPLETELY unnessecary以清除在构造函数中
  2. 这是unnessecary以清除在析构函数除非容器包含一个指向一个STL容器的内容STL容器的内容。如果已经使用创建了指针,则仍然需要先删除。在那之后,清理容器仍然不会是非常秘密的。

考虑一下:

#define BOOST_TEST_MODULE StlContainers 
#define BOOST_LIB_DIAGNOSTIC 

#include <boost/test/unit_test.hpp> 
#include <boost/assign.hpp> 
#include <boost/assign/list_of.hpp> 
#include <boost/assign/std/vector.hpp> 

#include <vector> 

using namespace boost::assign; 
using namespace std; 

const vector<int> my_ints_vector = list_of(0)(1)(1)(2)(3)(5)(8)(13)(21)(34); 

struct ScopedStruct1 
{ 
     ScopedStruct1(const vector<int> & v) : m_v(v) {} 
     ~ScopedStruct1() {} 
    private : 
     vector<int> m_v; 
}; 

class A 
{ 
    public : 
     A(int i) : m_i(i) {} 
     ~A() {} 
    private : 
     int m_i; 
}; 

struct ScopedStruct2 
{ 
    ScopedStruct2() {} 
    ~ScopedStruct2() { for(vector<A*>::iterator it = m_v.begin(); it != m_v.end(); ++it) delete *it; } 

    vector<A*> m_v; 
}; 

struct ScopedStruct3 
{ 
    ScopedStruct3() {} 
    ~ScopedStruct3() { /* no deletion */ } 

    vector<A*> m_v; 
}; 

BOOST_AUTO_TEST_CASE(StlContainer_storing_something_simple) 
{ 
    ScopedStruct1 str(my_ints_vector); 
} 

BOOST_AUTO_TEST_CASE(StlContainer_storing_pointers_with_delete) 
{ 
    ScopedStruct2 str; 
    for(int i = 0; i < 10; i++) 
     str.m_v.push_back(new A(i)); 
} 

BOOST_AUTO_TEST_CASE(StlContainer_storing_pointers_without_delete) 
{ 
    ScopedStruct3 str; 
    for(int i = 0; i < 10; i++) 
     str.m_v.push_back(new A(i)); 
} 

使用升压转换器的unit_test框架我创建了3测试用例。 unit_test框架是greate,因为它跟踪内存泄漏。 你会注意到第一个和第二个测试用例不会产生内存泄漏,但是第三种情况的确是因为矢量的内容没有被删除。

+0

带示例代码的唯一答案..很好! – nkint 2013-06-18 09:51:21

-4

当然,人们已经调用clear()或调整(0)或同等的发言权(STD :: _ Destroy_range(...)在析构函数重新分配前

重分配是通过分配器进行: :取消分配不运行任何析构函数它只是释放内存

明确的()相当于调整(0)运行在第一大小)的事情在分配的缓冲区析构函数(

NOT。只是分配了指针,文件句柄,持有mutexes,该对象持有的所有其他可回收资源。必须运行析构函数。在实例化之前,模板不知道析构函数是微不足道的。如果析构函数微不足道,那么它在实例化后得到优化

+1

不,当矢量超出范围时绝对会调用析构函数。不调用析构函数是没有意义的。我建议你仔细检查你的实施。您可以通过运行这样的测试: 的#include 的#include 结构测试{〜测试(){性病::法院<< “再见,世界\ n”; }}; int main(){std :: cout <<“Creating \ n”; std :: vector t(1); std :: cout <<“Created \ n”; } – janm 2009-10-20 00:47:17

+5

绝对不正确。 – 2009-10-20 00:51:35

+0

我在〜vector()中讨论了一个明确的调用,而不是讨论用户定义的类的向量成员实例变量的明确调用 - 我的误读。 – pgast 2009-10-23 07:06:31

1

我能想到的唯一情况是它的用处在于销毁的顺序和析构函数想要确保向量中的对象被销毁在别的之前。

当然,最好是结构化的代码不要求;然而,这是一个可以想象的理由。

1

尽管到目前为止所说的至少有一种情况,当在析构函数中显式调用clear可能是必要的。

想象一下,当被销毁的对象有多个成员子对象时,需要某种特定的销毁顺序,即子对象以某种方式相互依赖,并且其不正确的销毁顺序会导致不良结果。正如您可能知道的那样,成员子对象销毁的顺序(以及成员初始化)由成员在类定义中声明的顺序决定。因此,一种实现正确销毁顺序的方法是相应地安排成员声明。但是,首先,这不是一个非常好的解决方案。其次,破坏的期望顺序可能取决于某些运行时间条件。第三,所需的破坏顺序可能与想要的初始化顺序相矛盾。这一切都意味着通过重新安排声明来指挥正确的销毁顺序是不可能的(或明智的)。

在这种情况下,合理的方法可能是通过调用clean等方法手动清除一些关键成员子对象,直到销毁顺序依赖关系“消失”。我猜想,也许你看到的代码试图通过在战略上选择的vector子对象上调用clean来解决订购问题。

至于在构造函数中调用clean ......我不知道为什么有人会这样做。

+0

显然你生活在太重新的话:)每次我检查代码时,它试图在构造函数/析构函数中实现“干净”。关于你所描述的情况,我几乎不可能想到它。最好应该做的,以避免它,如果不可能应该很好地评论 – dimba 2009-10-20 04:00:47

+0

我可能是错的,但是当stl对象在范围的末尾死亡 - 例如。它调用内部对象的析构函数。如果该对象也是一个stl容器,它也应该自动清除它自己。由“新”发起的指针会出现异常情况 - 像往常一样 – Maciek 2009-10-20 23:42:33

+1

@Maciek:没有人会为此争论。我要说的是,在某些情况下,自动*清除的顺序可能是不可接受的。在自动清理开始之前,您可能需要自行定制预清理。 – AnT 2009-10-21 00:02:43

相关问题