C++ 像std::vector这样的向量类的简单实现
我正在实现一个简单的向量,比如std::vector,我编写了一些函数,而不用担心它提供了什么样的异常安全保证。我知道一些关于C++的异常,但是我没有经历过异常安全代码的编写。 这是我的密码:C++ 像std::vector这样的向量类的简单实现,c++,vector,stl,C++,Vector,Stl,我正在实现一个简单的向量,比如std::vector,我编写了一些函数,而不用担心它提供了什么样的异常安全保证。我知道一些关于C++的异常,但是我没有经历过异常安全代码的编写。 这是我的密码: template <typename T> class vector { public: vector(int _DEFAULT_VECTOR_SIZE = 10) : size(0), array_(new T[_DEFAULT_VECTOR_SIZE]), capaci
template <typename T>
class vector {
public:
vector(int _DEFAULT_VECTOR_SIZE = 10) :
size(0), array_(new T[_DEFAULT_VECTOR_SIZE]), capacity(_DEFAULT_VECTOR_SIZE) {}
void push_back(T& elem)
{
if (size == capacity)
resize(2 * size);
array_[size] = elem;
size++;
}
void pop_back()
{
--size;
}
void resize(int size_)
{
if (size_ > capacity)
{
T* temp = new T[size_];
memcpy(temp,array_,size*sizeof(T));
swap(temp, array_);
delete[] array_;
capacity = size_;
}
}
private:
T* array_;
int size;
int capacity;
};
模板
类向量{
公众:
向量(int\u默认值\u向量大小=10):
大小(0),数组(新的T[\u默认值\u向量\u大小]),容量(\u默认值\u向量\u大小){}
无效推回(T&elem)
{
如果(大小=容量)
调整大小(2*大小);
数组\[size]=elem;
大小++;
}
void pop_back()
{
--大小;
}
无效调整大小(整型大小)
{
如果(大小>容量)
{
T*temp=新的T[尺寸];
memcpy(温度、数组、大小*sizeof(T));
交换(临时、阵列);
删除[]数组;
容量=大小;
}
}
私人:
T*数组u;
整数大小;
国际能力;
};
所以我的问题是:我如何修改我的代码(函数),这将至少提供基本的保证,或者一些为基本或强保证编写异常安全代码的技术?
谢谢例外安全主要有两种口味:
memcpy
,因为这无法调用复制构造函数。例如,复制std::string
还应该复制字符缓冲区,字符串向量是一种您应该支持的完全正常的类型
让我们看看向量的复制构造函数。它需要复制源向量的每个元素。每个副本都可以抛出。如果其中一个字符串太长以至于副本抛出std::bad_alloc
,该怎么办
现在,异常安全意味着您使程序处于正常状态,因此不会出现内存泄漏。向量的复制ctor失败,因此dtor无法运行。那么谁来清理T*数组呢?这必须在您的副本中完成
当复制失败时,将不会有新的向量,因此您可以免费获得第二种类型的异常安全。(“强异常安全”)。但接下来让我们看看赋值运算符,v2=v1
。您将覆盖一个旧向量。如果先执行.resize(0)
,然后复制所有元素,则在复制过程中可能会遇到异常。原始矢量内容已消失,新内容不完整。不过,您还没有泄漏任何内存,也没有复制半个元素
为了使赋值安全,有一个简单的技巧:首先将源向量复制到临时向量。如果失败,则没有问题(见上文)。我们还没有到达目的地。但是如果赋值成功,我们交换临时向量和目标向量的数组*
指针、大小
和容量
。交换指针和整数是安全的(不能抛出)。最后,我们让临时向量超出范围,从而破坏不再需要的旧向量元素
因此,通过对临时对象执行所有危险的操作,我们可以确保任何异常都不会触及原始状态
您需要检查所有方法,看看这些问题是否会发生,但模式通常是相似的。如果元素副本或元素分配抛出,请不要泄漏数组,一定要将该异常传播给调用方。
尝试{/*抛出异常的代码*/}捕获{/*处理异常*/}
,据我记忆所及,我希望您意识到这有多错误:memcpy(temp,array,size*sizeof(t))
为什么memcpy(temp、array、size*sizeof(T))错误?@SenoAlvrtsyanmemcpy
只适用于int
等POD类型或非常简单的类。另见@SenoAlvrtsyan:简短回答:是。但您可以将其扩展为一个体面的新问题(请展示您的.resize
实现),并在该问题中解释您特别想知道std::copy
在使用时的异常安全性。