C++ 泛型堆栈类的异常安全代码

C++ 泛型堆栈类的异常安全代码,c++,exception,generics,c++11,C++,Exception,Generics,C++11,我正在尝试编写一个异常安全的通用堆栈。这就是我到目前为止所做的 #include <iostream> #include <memory> #include <exception> class stk_exception:public exception { virtual const char* what() const throw() { return "stack underflow"; } } stk_ex;

我正在尝试编写一个异常安全的通用堆栈。这就是我到目前为止所做的

#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();
}
#包括
#包括
#包括
类stk_异常:公共异常
{
虚拟常量char*what()常量throw()
{
返回“堆栈下溢”;
}
}stk_ex;
模板
结构节点
{
T数据;
节点*下一步;
};
模板
类堆栈\u泛型
{
公众:
堆栈_generic():_头(nullptr){
}
无效推力(T x){
节点*temp(新节点());
温度->数据=x;
温度->下一步=_头;
_压头=温度;
}            
void pop(){
如果(_head==nullptr){
投掷沙丁鱼;
}否则{
节点*温度=_头;
_头部=_头部->下一步;
删除临时文件;
返回;
}
}
T top(){
T x=T();
如果(_head==nullptr){
投掷沙丁鱼;
}否则{
返回头->数据;
}
}
私人:
节点*头;
};
int main()
{
堆栈(s),;
s、 推(1);
s、 推(2);

std::cout以下实现应该(几乎)是异常安全的:

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{};
    }
}
void push(T x){
head=新节点{std::move(x),head};
}
T pop(无效){
若有(总目){
T结果{std::move(head->data)};
自动旧=头;
头部=头部->下一步;
删除旧的;
返回结果;
}否则{

cout最佳实践是使用
std::shared\u ptr

#include <iostream>
#include <memory>
#include <exception>


template <class T>
class node
{
public:
    node(T data, std::shared_ptr<node<T>> next)
        : _data(data), _next(next)
    {
    }

    T data() const
    {
        return _data;
    }

    std::shared_ptr<node<T>> next() const
    {
        return _next;
    }

private:
    T _data;
    std::shared_ptr<node<T>> _next;
};


template <class T>
class stack_generic
{
public:
    stack_generic()
        : _head(nullptr)
    {
    }

    void push(T x)
    {
        _head = std::make_shared<node<T>>(x, _head);
    }

    T pop()
    {
        if (_head == nullptr) {
            throw std::underflow_error("underflow");
        } else {
            std::shared_ptr<node<T>> temp = _head;
            _head = _head->next();
            return temp->data();
        }
    }

private:
    std::shared_ptr<node<T>> _head;
};


int main()
{
    stack_generic<int> s;
    s.push(1);
    s.push(2);
    std::cout << s.pop();
    std::cout << s.pop();
}
#包括
#包括
#包括
模板
类节点
{
公众:
节点(T数据,std::shared\u ptr next)
:_数据(数据),_下一个(下一个)
{
}
T data()常量
{
返回数据;
}
std::shared_ptr next()常量
{
返回下一步;
}
私人:
T_数据;
std::共享\u ptr\u next;
};
模板
类堆栈\u泛型
{
公众:
堆栈_泛型()
:_head(nullptr)
{
}
无效推力(T x)
{
_head=std::使_共享(x,_head);
}
T pop()
{
如果(_head==nullptr){
抛出标准::下溢错误(“下溢”);
}否则{
标准::共享温度=_头;
_头=_头->下一步();
返回temp->data();
}
}
私人:
std::共享ptr头;
};
int main()
{
堆栈(s),;
s、 推(1);
s、 推(2);

STD::CUT 1。请不要使用“NULL”用于C++代码,使用“NulLPTR”相反。2.你的代码格式就像一张名片。如果看起来凌乱,那就是你的第一印象。哪一行?唯一的\u ptr在哪里?std::unique\u ptr
的默认复制构造函数和复制赋值运算符已被删除,因为它们不存在。要使用
unique\u ptr
,你需要使用而不是复制。@ Flovdis: NulLPTR> /Cord>只是一个选项,如果代码只需要在C++ 11编译器上编译。但是,在这种情况下,我同意NulLPTR是更好的解决方案。也许另一种选择是检查C++版本,并使用<代码>定义旧版本的NulLPTR NULL/<代码>。code>unique\u ptr
也需要C++11,并且在这个问题上有一个C++11标记。+1用于提及单独的
top
pop
方法。使用单独的
top
pop
函数是
std::stack
避免这个问题的方法。更喜欢
std::make\u shared
而不是构建
new
@YoungJohn共享的
好主意,让我来解决这个问题。谢谢。