手动调用析构函数导致C++ Creature对象重复销毁问题求助
问题分析与解决方案
问题根源
你手动调用c.~Creature()销毁栈对象的操作是错误的:
- 栈上的变量
c1会在main函数结束时由编译器自动触发析构函数,这就导致同一对象被析构两次。 - 第一次手动析构后,对象内存已被标记为无效,第二次自动析构时访问
name会出现空值,所以输出is destroyed.。 - C++中栈对象的生命周期由编译器管理,手动调用析构函数属于未定义行为,绝对不能这么做。
另外你写的检查条件还有错误:原代码里判断strength >100不符合题目要求(题目要求strength范围是0-50),且getPV() ==0 || getPV() <=0是重复判断,正确的边界应该是hp <0 || hp>100、strength <0 || strength>50。
可行解决方案
方案1:使用动态分配对象(推荐)
将对象改为堆上分配,不符合条件时用delete手动销毁,避免栈对象的自动析构冲突:
void checkCreature(Creature* c) { // 修正边界判断逻辑 if (c->getPV() < 0 || c->getPV() > 100 || c->getStrength() < 0 || c->getStrength() > 50) { delete c; c = nullptr; // 置空指针,避免野指针问题 } } int main() { Creature* c1 = new Creature(); c1->fillCreature(); c1->creatureShowInfo(); checkCreature(c1); // 检查指针有效性,避免重复delete if (c1 != nullptr) { delete c1; } return 0; }
方案2:用工厂函数创建有效对象
给Creature类添加静态工厂函数,只有属性符合要求时才返回有效对象,否则返回空:
#include <optional> #include <string> #include <iostream> class Creature { private: std::string name; int pv; int strength; // 私有构造函数,强制通过工厂创建对象 Creature(const std::string& n, int h, int s) : name(n), pv(h), strength(s) {} public: // 工厂函数:检查属性合法性,返回可选对象 static std::optional<Creature> create(const std::string& name, int hp, int strength) { if (hp >= 0 && hp <= 100 && strength >= 0 && strength <= 50) { return Creature(name, hp, strength); } return std::nullopt; } void creatureShowInfo() { std::cout << "Name : " << name << "\nHP : " << pv << "\nStrength : " << strength << std::endl; } ~Creature() { std::cout << name << " is destroyed." << std::endl; } }; int main() { std::string name; int hp, strength; // 模拟输入逻辑 std::cout << "Creature's name :"; std::cin >> name; std::cout << "Creature's health (between 0 and 100) :"; std::cin >> hp; std::cout << "Creature's strength (between 0 and 50) :"; std::cin >> strength; auto creatureOpt = Creature::create(name, hp, strength); if (creatureOpt) { creatureOpt->creatureShowInfo(); } else { std::cout << "Strength value incorrect." << std::endl; } return 0; }
方案3:标记对象为无效状态
如果必须使用栈对象,可以给类添加isValid标记,析构函数只在对象有效时输出信息:
class Creature { private: std::string name; int pv; int strength; bool isValid = true; // 标记对象是否有效 public: // 成员函数实现... void invalidate() { isValid = false; // 可在此清理资源,但不要调用析构 } int getPV() const { return pv; } int getStrength() const { return strength; } void fillCreature() { /* 原输入逻辑 */ } void creatureShowInfo() { /* 原输出逻辑 */ } ~Creature() { if (isValid) { std::cout << name << " is destroyed." << std::endl; } } friend void checkCreature(Creature& c); }; void checkCreature(Creature& c) { if (c.getPV() < 0 || c.getPV() > 100 || c.getStrength() < 0 || c.getStrength() > 50) { c.invalidate(); } } int main() { Creature c1; c1.fillCreature(); c1.creatureShowInfo(); checkCreature(c1); return 0; }
内容的提问来源于stack exchange,提问作者Hugo Angel
相关产品推荐
相关产品推荐

