C++中Symbol类+运算符重载及代码冗余规避方案咨询
解决Symbol类与double相加的运算符重载冗余及段错误问题
问题根源分析
你的代码存在两个核心问题:
- 代码冗余:
Symbol+double的实现逻辑与Symbol+Symbol高度重复,未复用已有代码。 - 悬挂指针与内存问题:
- 原
operator+(Symbol other)中,temp.right = &other将指针指向函数局部参数(值传递的副本),函数返回后该参数被销毁,后续访问会触发段错误。 - 方式1用
new动态分配Symbol但未管理内存,造成内存泄漏;方式2中动态分配的对象在函数结束后未释放,且传递给operator+(Symbol)时产生的副本销毁后,表达式树的指针仍指向无效内存。
- 原
最优实现方案
改用智能指针管理内存(避免手动内存管理错误),同时重构运算符重载逻辑以复用代码:
完整修正代码
#include <iostream> #include <memory> #include <string> class Symbol{ public: std::string name = ""; bool is_constant = false; bool is_expression = false; char op; double value = 0.0; std::unique_ptr<Symbol> left; std::unique_ptr<Symbol> right; // 构造函数 Symbol() : is_expression(true) {} Symbol(std::string name) : name(std::move(name)) {} Symbol(double value) : value(value), is_constant(true) {} // 克隆方法:复制Symbol节点,构建独立的表达式树分支 std::unique_ptr<Symbol> clone() const { auto ptr = std::make_unique<Symbol>(); ptr->name = name; ptr->is_constant = is_constant; ptr->is_expression = is_expression; ptr->op = op; ptr->value = value; if (left) ptr->left = left->clone(); if (right) ptr->right = right->clone(); return ptr; } // Symbol与Symbol相加:核心逻辑实现 Symbol operator+(const Symbol& other) const { // 两个常量直接计算结果 if (is_constant && other.is_constant) { return Symbol(value + other.value); } // 构建表达式树节点 Symbol temp; temp.op = '+'; temp.left = this->clone(); temp.right = other.clone(); return temp; } // Symbol与double相加:直接复用Symbol+Symbol逻辑 Symbol operator+(double other) const { return *this + Symbol(other); } // 打印表达式树 void print() const { if (is_expression) { std::cout << "( "; left->print(); std::cout << op << " "; right->print(); std::cout << ") "; return; } if (is_constant) { std::cout << value << " "; return; } std::cout << name << " "; } }; // 全局重载:支持double + Symbol的反向表达式 Symbol operator+(double lhs, const Symbol& rhs) { return Symbol(lhs) + rhs; } int main(){ Symbol x("x"); Symbol z = x + 2.3; z.print(); // 测试反向相加场景 Symbol w = 5.1 + x; std::cout << "\n"; w.print(); }
关键改进点
- 智能指针管理内存:用
std::unique_ptr<Symbol>替代裸指针,自动管理内存生命周期,彻底避免悬挂指针和内存泄漏。 - 复用核心逻辑:
Symbol+double通过构造临时Symbol(double)对象,直接复用已有的Symbol+Symbol运算符重载,消除代码冗余。 - 克隆方法:通过
clone()复制节点,确保表达式树的每个分支都拥有独立内存空间,避免指针指向临时对象。 - 双向相加支持:新增全局
operator+(double, const Symbol&),实现5.1 + x这类反向表达式。
运行结果
执行main函数后输出:
( x + 2.3 ) ( 5.1 + x )
内容的提问来源于stack exchange,提问作者Aditya Vinchhi
相关产品推荐
相关产品推荐

