我无法使用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;
}
答案 0 :(得分:5)
代码中有几件事。我仍然无法理解为什么在某些环境中禁止使用STL,当它经过彻底的测试并且相当便宜时(包括STL或任何其他模板化代码,你只编译你使用的部件)......这迫使人们重新发明轮子等等通常情况下,它会以粗糙的角落结束。
我会开始讨论STL被禁止的原因,并试图找出之前允许的库(如果决定性能,请考虑STL的Electronic Arts版本,如果他们不信任VC6 STL实现,请考虑STLPort )。在质量上开发接近STL的任何东西需要相当多的努力和知识。
现在到你的容器。首先,您要首先定义类要求,要对向量及其元素执行哪些操作。您的代码的限制是:
您的代码有些特别之处:
const T*
,因此在构建后无法更改。explicit
,以避免不必要的隐式转换。有些注意事项......你不能使用STL,但你可以使用属于STL的std::copy
吗? STL的哪些部分超出限制?
答案 1 :(得分:4)
此默认值构造新对象并分配它们(或者,如果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());
}
if语句是多余的。 NULL指针上的delete[]
没问题。此外,有任何意义,它是虚拟的吗?看起来这不是一个旨在派生出来的类。
template <typename T>
StdVector<T>::~StdVector(){
if (_items != NULL)
delete[] _items;
}
SetSize会销毁所有对象并创建新对象。这可能是“令人惊讶”的行为。此外,如果new
抛出,则对象将指向释放的内存。再次,如果保护删除是多余的。
template <typename T>
void StdVector<T>::SetSize(int size){
if (_items != NULL)
delete[] _items;
_pos = 0;
_size = size;
_items = new T[_size];
}
这有什么意义?它似乎与Begin
相同。它甚至不是const方法。
template <typename T>
const T * StdVector<T>::ConstIterator(){
return _items;
}
此尝试不会复制到刚刚删除的_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;
}
这是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;
}
答案 2 :(得分:2)
一些快速评论:
额外奖励:您可以查看Stepanov的lecture notes(pdf)for Adobe。前几章是关于矢量类的设计。