如何将现有C++链式栈代码修改为完全使用智能指针实现
C++ 链式栈智能指针改造实现
核心改造规则
- 所有内存管理替换为
std::unique_ptr,完全消除new、delete操作与持有所有权的原始指针声明 - 移除冗余析构函数:智能指针自动管理资源生命周期,无需手动销毁节点
- 尽可能使用
auto推导类型,减少冗余类型声明 - 保留原接口所有功能、异常逻辑与性能表现
完整改造后代码
#include <memory> #include <string> #include <utility> #include "PrecondViolatedExcep.h" template<typename ItemType> class Node { private: ItemType item; std::unique_ptr<Node<ItemType>> next; public: Node(const ItemType& val) : item(val) {} Node(const ItemType& val, std::unique_ptr<Node<ItemType>> nextPtr) : item(val), next(std::move(nextPtr)) {} ItemType getItem() const { return item; } const std::unique_ptr<Node<ItemType>>& getNext() const { return next; } void setNext(std::unique_ptr<Node<ItemType>> nextPtr) { next = std::move(nextPtr); } }; template<typename ItemType> class LinkedStack { private: std::unique_ptr<Node<ItemType>> topPtr; public: LinkedStack() = default; LinkedStack(const LinkedStack<ItemType>& aStack); // 移动构造默认生成即可,无需手动实现 LinkedStack(LinkedStack<ItemType>&&) = default; LinkedStack& operator=(LinkedStack<ItemType>) = default; // 复制交换惯用法 bool isEmpty() const; bool push(const ItemType& newItem); bool pop(); ItemType peek() const; }; // 以下为对应成员函数改造实现 template <typename ItemType> LinkedStack<ItemType>::LinkedStack(const LinkedStack<ItemType>& aStack) { if (!aStack.topPtr) { return; } // 仅使用临时观察指针遍历,不持有所有权 auto origStackPtr = aStack.topPtr.get(); try { topPtr = std::make_unique<Node<ItemType>>(origStackPtr->getItem()); auto newStackPtr = topPtr.get(); origStackPtr = origStackPtr->getNext().get(); while (origStackPtr) { newStackPtr->setNext( std::make_unique<Node<ItemType>>(origStackPtr->getItem()) ); newStackPtr = newStackPtr->getNext().get(); origStackPtr = origStackPtr->getNext().get(); } } catch (const std::bad_alloc&) { topPtr.reset(); // 智能指针自动释放所有已分配资源 throw; } } template <typename ItemType> bool LinkedStack<ItemType>::isEmpty() const { return !topPtr; } template <typename ItemType> bool LinkedStack<ItemType>::push(const ItemType& newItem) { try { topPtr = std::make_unique<Node<ItemType>>(newItem, std::move(topPtr)); } catch (const std::bad_alloc&) { return false; } return true; } template <typename ItemType> bool LinkedStack<ItemType>::pop() { if(!isEmpty()) { auto nodeToDelete = std::move(topPtr); topPtr = std::move(const_cast<std::unique_ptr<Node<ItemType>>&>(nodeToDelete->getNext())); return true; } return false; } template <typename ItemType> ItemType LinkedStack<ItemType>::peek() const { if (isEmpty()) { std::string message("LinkedStack::peek() "); message += "called on an empty stack."; throw PrecondViolatedExcep(message); } return topPtr->getItem(); }
关键改造说明
- 采用
std::unique_ptr管理节点所有权,无循环引用风险,内存开销与原始指针基本一致 - 所有节点创建使用
std::make_unique,完全消除显式new操作 - 移除手动析构函数,智能指针自动递归释放所有节点资源
pop函数中通过所有权转移的方式销毁节点,无需手动调用delete- 仅在遍历节点时使用
get()获取临时观察指针,未声明任何持有所有权的原始指针变量
内容的提问来源于stack exchange,提问作者finn2021
相关产品推荐
相关产品推荐

