首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++:自定义编码泛型容器的潜在问题?

C++:自定义编码泛型容器的潜在问题?
EN

Stack Overflow用户
提问于 2009-11-28 19:05:59
回答 3查看 197关注 0票数 1

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

我并没有实际测试过代码,但是我担心这个泛型容器是否可以同时使用原始类型和非原始类型(如class)。特别是复制构造函数和赋值操作符会有什么潜在的问题吗?

我们非常欢迎任何其他的建议和意见。:)

代码语言:javascript
复制
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;
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2009-11-28 19:22:31

默认情况下会构造新对象并分配它们(或者,如果Begin()返回T*而不是const T*,请参阅dribeas的答案),如果您使用原始存储并就地构造新对象,可能会更有效。同样,由于GetSize()Begin()End()不是常量,因此不能在参数v上调用它们。

代码语言:javascript
复制
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());
}

if语句是多余的。空指针上的delete[]就可以了。另外,它是虚拟的有什么意义吗?它看起来不像是一个被设计为派生的类。

代码语言:javascript
复制
template <typename T>
StdVector<T>::~StdVector(){
    if (_items != NULL)
            delete[] _items;
}

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

代码语言:javascript
复制
template <typename T>
void StdVector<T>::SetSize(int size){
    if (_items != NULL)
            delete[] _items;

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

这有什么意义呢?它似乎和Begin做同样的事情。它甚至不是const方法。

代码语言:javascript
复制
template <typename T>
const T * StdVector<T>::ConstIterator(){
    return _items;
}

这个尝试不会复制到刚刚被删除的_items (再次参见关于Begin()返回const T*和关于Begin()End()不是常量的要点)?

代码语言:javascript
复制
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;
}

这是什么exception类?std::exception没有一个接受const char*的构造函数。您还应该抛出异常对象,而不是指向动态分配的异常对象的指针。清除由指针“抛出”的动态分配的异常几乎是不可能的。

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

    _items[_pos++] = item;
}
票数 5
EN

Stack Overflow用户

发布于 2009-11-28 19:44:08

代码中有几件事。我仍然不能理解为什么在一些环境中使用STL是被禁止的,因为它是经过全面测试的,而且相当便宜(当包含STL或任何其他模板代码时,您只编译您使用的部分)……这迫使人们重新发明轮子,往往以粗糙的弯道告终。

我会开始讨论为什么禁止STL,并尝试制定一个以前允许的库(如果是性能方面的决定,请考虑电子艺界版本的STL,如果他们不信任VC6 STL实现,则考虑STLPort )。开发在质量上接近STL的任何东西都需要相当多的努力和知识。

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

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

你的代码中有一些特殊的东西:

construction.

  • Even

  • 复制初始化和赋值是不可能的:存储是const T*的,因此在construction.

  • Even之后不能更改。赋值不是异常安全的

  • 向量中的所有元素(无论是否使用)都已构造(您正在为未使用的elements)

  • All单参数构造函数(但复制构造函数)的构造买单)应为

以避免不需要的隐式构造函数,并且返回迭代器的方法应为常量。

一些附注。你不能使用STL,但你可以使用STL中的std::copy?STL的哪些部分超出了限制?

票数 5
EN

Stack Overflow用户

发布于 2009-11-28 19:18:58

以下是一些简短的说明:

在std::copy statement

  • Performance issue:
  1. T_size会导致默认构造函数被_size调用的时候,你应该写的单元会崩溃。你也不应该要求T有一个默认的constructor.
  2. The机制,因为SetSize很奇怪。您应该尝试通过在需要时扩展大小来模拟std::vector的行为。

额外的好处:你可能想看看Stepanov的lecture notes。前几章是关于向量类的设计。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1812259

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档