2015-10-22 30 views
2

我用C++初学者,尝试创建类似于Vector的容器类。这个类应该像Vector一样适用于所有类型的数据,并且可以在基于范围的for循环中使用。 我写了hpp但我的导师说有内存泄漏,我想我删除了所有的动态内存,哪里可能是问题?C++:内存泄漏;向量级类

#include "stdafx.h" 
using namespace std; 
template<class T> 
class Customvector 
{ 
public: 
    Customvector(); 
    ~Customvector(); 
    int size(); 
    int free_capacity(); 
    void add(T& temp); 
    int& operator[](int index); 
    void grow(); 

    class iterator { 
     public: 
      iterator(T* ptr) : ptr(ptr) {} 
      iterator operator++() { iterator i(ptr); ++ptr; return i; } 
      bool operator!=(const iterator & other) { return ptr != other.ptr; } 
      const T& operator*() const { return *ptr; } 
     private: 
      T* ptr; 
     }; 

    iterator begin() const { return iterator(&_elements[0]); } 
    iterator end() const { return iterator(&_elements[0]+_size); } 
private: 
    T* _elements; 
    int _size; 
    int _capacity; 
    int DEFAULT_CAPACITY; 
}; 

template<class T> 
Customvector<T>::Customvector() 
{ 
    DEFAULT_CAPACITY = 4; 
    _capacity = DEFAULT_CAPACITY; 
    _size = 0; 
    _elements = new T[_capacity]; 

} 
template<class T> 
Customvector<T>::~Customvector() 
{ 
    delete[] _elements; 

} 
template<class T> 
void Customvector<T>::add(T& temp) 
{ 
    grow(); //check if the capacity is full, if so,increase capacity by DEFAULt_CAPACITY; 
    _elements[_size++]= temp; 

} 
template<class T> 
int Customvector<T>::size() 
{ 
    return _size; 
} 

template<class T> 
int Customvector<T>::free_capacity() 
{ 
    int free_c = _capacity - _size; 
    return free_c; 
} 


template<class T> 
int& Customvector<T>::operator[](int index) { 
    if (index<0 || index>_capacity) 
    { 
     cout << "index beyond limit" << endl; 
     return _elements[0]; 
    }; 
    return _elements[index]; 
} 

template<class T > 
void Customvector<T>::grow() 
{ 
    if (_capacity == _size) 
    { 
     _capacity += DEFAULT_CAPACITY; 
     T* p = new T[_capacity]; 
     std::copy(_elements, _elements + _size,p); 
     delete[] _elements; 
     _elements = p; 
    }; 

} 
+2

你可能想了解(http://en.cppreference.com/w/cpp/language/rule_of_three)的三,五和零规则。 –

+0

首先,你没有一个析构函数中的迭代器类这可能是在那里你'删除[] ptr' – TriHard8

+0

此外,你有*未定义行为*在'运营商[]'功能,如果你在传递非法索引和向量是空的。你分配的数据内容是* indeterminate *,并且除了初始化数据外,任何其他方式都会导致未定义的行为。 –

回答

3

我能找到的唯一的漏水情况是grow

... 
    T* p = new T[_capacity]; 
    std::copy(_elements, _elements + _size,p); // may throw an exception 
    delete[] _elements; 
    _elements = p; 
    ... 

如果包含的元素复制抛出,然后_elements仍然指向旧阵列和新阵列由p泄漏指出。你可以用unique_ptr解决此问题:

std::unique_ptr<T[]> p(new T[_capacity]); 
std::copy(_elements, _elements + _size, p.get()); // it's OK if this throws, unique_ptr will take care of the memory 
delete[] _elements; 
_elements = p.release(); 

使用unique_ptr_elements也将简化一些代码,提高正确性。

+0

我不明白异常是如何工作的,我的意思是: std :: copy(_elements,_elements + _size,p); //如果这里抛出一个异常,它会跳出整个范围,或者只是这一行代码? –

+0

@LiZeng例外在这里工作的方式与他们在任何地方都一样。当一个对象被抛出时,范围被退出。如果该对象没有被任何catch表达式捕获,则更高的作用域将被递归地退出,直到被捕获的对象被捕获。 – user2079303