cla*_*ius 3 c++ generics exception c++11
我正在尝试编写一个异常安全的通用堆栈.这就是我到目前为止所做的.
#include <iostream>
#include <memory>
#include <exception>
class stk_exception:public exception
{
virtual const char* what() const throw()
{
return "stack underflow";
}
} stk_ex;
template <class T>
struct node
{
T data;
node<T> *next;
};
template <class T>
class stack_generic
{
public:
stack_generic() : _head(nullptr) {
}
void push(T x) {
node<T> *temp(new node<T>());
temp->data = x;
temp->next = _head;
_head = temp;
}
void pop() {
if (_head == nullptr) {
throw stk_ex;
} else {
node<T> *temp = _head;
_head = _head->next;
delete temp;
return;
}
}
T top() {
T x = T();
if (_head == nullptr) {
throw stk_ex;
} else {
return _head->data;
}
}
private:
node<T> *_head;
};
int main()
{
stack_generic<int> s;
s.push(1);
s.push(2);
std::cout << s.top();
s.pop();
std::cout << s.top();
s.pop();
}
Run Code Online (Sandbox Code Playgroud)
我可以使用STL列表/向量来实现RAII,但我想使用原始指针.因此,当我使用unique_ptr将头指针包装在堆栈中时,它会抛出一个编译错误"对于调用unique_ptr,default_delete没有匹配的函数.这里有什么问题?有人可以建议我该怎样做才能使这个类异常安全吗?谢谢!
编辑:为下溢添加了异常处理.定义了单独的top和pop方法
以下实现应该(几乎)异常安全:
void push(T x) {
head = new node<T>{std::move(x), head};
}
T pop(void) {
if (head) {
T result{std::move(head->data)};
auto old = head;
head = head->next;
delete old;
return result;
} else {
cout << "underflow!";
return T{};
}
}
Run Code Online (Sandbox Code Playgroud)
这段代码的唯一问题是return result.通常,此操作可能会抛出异常,在这种情况下,调用者会看到异常,但堆栈仍然会发生更改.
您可以通过将函数分成两个函数来避免此问题.第一个函数返回top元素,第二个函数删除它.