C++:自定义编码通用容器的潜在问题?

Lop*_*per 1 c++

我无法使用STL和boost库,我必须用C++编写自己的容器.以下代码在VC++ 6中编译时没有错误.

我实际上没有测试过代码,但是关心这个通用容器是否适用于原始类型和非原始类型(如类).复制构造函数和赋值运算符是否会出现任何潜在问题?

欢迎任何其他建议和意见.:)

template <class T>  
class __declspec(dllexport) StdVector{

private:  
    int _pos;  
    int _size;  
    const T *_items;  

public:
    StdVector();
    StdVector(const StdVector &v);
    StdVector(int size);
    virtual ~StdVector();

    void Add(const T &item);
    void SetSize(int size);
    int GetSize();

    const T * Begin();
    const T * End();
    const T * ConstIterator();

    StdVector & operator=(const StdVector &v);
};

template <typename T>
StdVector<T>::StdVector() 
    : _pos(0), _size(0), _items(NULL){
}

template <typename T>
StdVector<T>::StdVector(const StdVector &v) 
    : _pos(0), _size(v.GetSize()), _items(new T[_size]){
    std::copy(v.Begin(), v.End(), Begin());
}

template <typename T>
StdVector<T>::StdVector(int size) 
    : _pos(0), _size(size), _items(new T[_size]){
}

template <typename T>
StdVector<T>::~StdVector(){
    if (_items != NULL)
        delete[] _items;
}

template <typename T>
void StdVector<T>::Add(const T &item){
    if (_pos == _size)
        throw new exception("Already at max size!!!");

    _items[_pos++] = item;
}

template <typename T>
void StdVector<T>::SetSize(int size){
    if (_items != NULL)
        delete[] _items;

    _pos = 0;
    _size = size;
    _items = new T[_size];
}

template <typename T>
int StdVector<T>::GetSize(){
    return _size;
}

template <typename T>
const T * StdVector<T>::Begin(){
    return _items;
}

template <typename T>
const T * StdVector<T>::End(){
    return _items + _pos;
}

template <typename T>
const T * StdVector<T>::ConstIterator(){
    return _items;
}

template <typename T>
StdVector<T> & StdVector<T>::operator=(const StdVector &v){
    if (this != &v){
        delete[] _items;
        std::copy(v.Begin(), v.End(), Begin());
    }

    return *this;
}
Run Code Online (Sandbox Code Playgroud)

CB *_*ley 5

此默认值构造新对象并分配它们(或者,如果Begin()返回的T*不是const T*,请参见dribeas的回答),如果您使用原始存储并就地构造新对象,则效率可能更高。另外,作为GetSize()Begin()End()不是常量,他们不能在参数调用v

template <typename T>
StdVector<T>::StdVector(const StdVector &v) 
    : _pos(0), _size(v.GetSize()), _items(new T[_size]){
    std::copy(v.Begin(), v.End(), Begin());
}
Run Code Online (Sandbox Code Playgroud)

if语句是多余的。delete[]在NULL指针上就可以了。此外,是否有任何迹象表明它是虚拟的?看起来这不是旨在派生的类。

template <typename T>
StdVector<T>::~StdVector(){
    if (_items != NULL)
            delete[] _items;
}
Run Code Online (Sandbox Code Playgroud)

SetSize销毁所有对象并创建新对象。这可能是“令人惊讶的”行为。同样,如果new抛出该对象,则该对象将指向已释放的内存。同样,如果保护删除是多余的。

template <typename T>
void StdVector<T>::SetSize(int size){
    if (_items != NULL)
            delete[] _items;

    _pos = 0;
    _size = size;
    _items = new T[_size];
}
Run Code Online (Sandbox Code Playgroud)

这有什么意义呢?它似乎与相同Begin。它甚至不是const方法。

template <typename T>
const T * StdVector<T>::ConstIterator(){
    return _items;
}
Run Code Online (Sandbox Code Playgroud)

难道这不是_items刚刚删除的尝试副本(再次参见有关Begin()返回const T*和关于Begin()End()不是const 的要点)吗?

template <typename T>
StdVector<T> & StdVector<T>::operator=(const StdVector &v){
    if (this != &v){
        delete[] _items;
        std::copy(v.Begin(), v.End(), Begin());
    }

    return *this;
}
Run Code Online (Sandbox Code Playgroud)

exception是什么班?std::exception没有采用的构造函数const char*。您还应该抛出异常对象,而不是动态分配的异常对象的指针。几乎不可能可靠地清除由指针“抛出”的动态分配的异常。

template <typename T>
void StdVector<T>::Add(const T &item){
    if (_pos == _size)
            throw new exception("Already at max size!!!");

    _items[_pos++] = item;
}
Run Code Online (Sandbox Code Playgroud)


Dav*_*eas 5

代码中有几件事.我仍然无法理解为什么在某些环境中禁止使用STL,当它经过彻底测试并且相当便宜时(包括STL或任何其他模板化代码,你只编译你使用的部件)......这迫使人们重新发明轮子等等通常情况下,它会以粗糙的角落结束.

我将开始讨论STL被禁止的原因,并试图找出之前允许的库(如果决定性能,请考虑STL的Electronic Arts版本,如果他们不信任VC6 STL实现,请考虑STLPort).在质量上开发接近STL的任何东西需要相当多的努力和知识.

现在到你的容器.首先,您要首先定义类要求,要对向量及其元素执行哪些操作.您的代码的限制是:

  • 存储的元素是常量:它们不能被更改
  • 你不能从矢量中删除元素
  • 您的调整大小操作将销毁所有存储的元素,它不能非破坏性地增长/缩小(我不确定这是一个接口限制还是您提供的实现的问题)

您的代码的一些特殊事项:

  • 复制初始化和分配是不可能的:存储是const T*,因此在构建后不能更改.
  • 即使有可能,分配也不例外
  • 构造向量中的所有元素(使用或不使用)(您为构建未使用的元素付费)
  • 所有单参数构造函数(但复制构造函数)应该是explicit为了避免不必要的隐式转换.
  • GetSize和返回迭代器的方法应该是常量.

一些附注......你不允许使用STL,但你可以使用STL的std::copy一部分吗?STL的哪些部分超出限制?