将引用函数转为指针函数出错,求C++指针问题排查指引
C++指针容器排序与遍历问题修复
我是C++新手,对指针还没完全掌握。之前用存储引用的vector实现的代码能正常编译,但改成存储CharacterBase对象指针后程序无法运行。现在sort的比较器测试时会崩溃,循环处理指针容器也有问题。我的目标是让vector存放PC和Enemy的CharacterBase指针,通过循环设置并显示指针指向对象的属性。相关代码如下:
void EVoot::IRollTwoCombatantsPtrs(CharacterBase& PC, CharacterBase& Enemy) { CharacterBase* player_ptr = nullptr; CharacterBase* enemy_ptr = nullptr; player_ptr = &PC; enemy_ptr = &Enemy; std::vector<CharacterBase*> ptrCharacterTurnOrderArray; ptrCharacterTurnOrderArray.push_back(player_ptr); ptrCharacterTurnOrderArray.push_back(enemy_ptr); sort(ptrCharacterTurnOrderArray.begin(), ptrCharacterTurnOrderArray.end(), [&](const CharacterBase& Char1, const CharacterBase& Char2) { //First Argument Stays First (Return true) if (Char1.getCharacterInitiative() < Char2.getCharacterInitiative()) { return true; } //First Argument goes Next (Swap) (Return false) if (Char1.getCharacterInitiative() > Char2.getCharacterInitiative()) { return false; } if (Char1.getCharacterInitiative() == Char2.getCharacterInitiative()) { engineFeedback = engineFeedback + "\n Error, matching initiative values found between " + Char1.getCharacterName() + " and " + Char2.getCharacterName(); } }); //The order needs to be reversed so that the highest turn order appears first. reverse(ptrCharacterTurnOrderArray.begin(), ptrCharacterTurnOrderArray.end()); TurnOrderArraySize = ptrCharacterTurnOrderArray.size(); engineFeedback = engineFeedback + "\nTurn Order Array Size: " + std::to_string(TurnOrderArraySize); //Set Turn orders now and provide a readout of the values for each item within the character Turn Order Array. for (auto iterator = ptrCharacterTurnOrderArray.begin(); iterator != ptrCharacterTurnOrderArray.end(); iterator++) { engineFeedback = engineFeedback + "\n Name: " + iterator.getCharacterName() + " Initiative: " + std::to_string(*iterator->getCharacterInitiative()) + " Player Character Flag: " + std::to_string(iterator->getIsPlayerCharacter()); iterator->setCharacterTurnOrder(iterator - ptrCharacterTurnOrderArray.begin() + 1); engineFeedback = engineFeedback + "\nTurn Order: " + std::to_string(iterator->getCharacterTurnOrder()); } } CharacterBase::CharacterBase() { } double CharacterBase::getCharacterInitiative() const { return cInitiative; } void CharacterBase::setCharacterInitiative(double sInitiative) { cInitiative = sInitiative; } //gets the Character's turn order int CharacterBase::getCharacterTurnOrder() const { return cTurnOrder; } //sets the Character's turn order void CharacterBase::setCharacterTurnOrder(int sTurnOrder) { cTurnOrder = sTurnOrder; } double cInitiative; int cTurnOrder;
核心错误点
- sort比较器参数类型不匹配:vector存储的是
CharacterBase*指针,但比较器接收const CharacterBase&引用,sort会把指针地址直接当成对象内存访问,触发内存越界崩溃。 - 比较器缺少默认返回值:当角色initiative相等时,比较器未返回任何值,触发C++未定义行为,导致程序崩溃或逻辑混乱。
- 迭代器访问语法错误:迭代器指向的是指针,需先解引用迭代器拿到指针,再通过
->访问对象成员,当前写法(如iterator.getCharacterName())完全错误。
修正后的完整代码
void EVoot::IRollTwoCombatantsPtrs(CharacterBase& PC, CharacterBase& Enemy) { CharacterBase* player_ptr = &PC; CharacterBase* enemy_ptr = &Enemy; std::vector<CharacterBase*> ptrCharacterTurnOrderArray; ptrCharacterTurnOrderArray.push_back(player_ptr); ptrCharacterTurnOrderArray.push_back(enemy_ptr); // 修正比较器参数为指针类型,补全返回值 sort(ptrCharacterTurnOrderArray.begin(), ptrCharacterTurnOrderArray.end(), [&](const CharacterBase* Char1, const CharacterBase* Char2) { if (Char1->getCharacterInitiative() < Char2->getCharacterInitiative()) { return true; } if (Char1->getCharacterInitiative() > Char2->getCharacterInitiative()) { return false; } // 相等时返回false(可根据需求调整逻辑) engineFeedback += "\nError, matching initiative values found between " + Char1->getCharacterName() + " and " + Char2->getCharacterName(); return false; }); reverse(ptrCharacterTurnOrderArray.begin(), ptrCharacterTurnOrderArray.end()); TurnOrderArraySize = ptrCharacterTurnOrderArray.size(); engineFeedback += "\nTurn Order Array Size: " + std::to_string(TurnOrderArraySize); // 修正迭代器访问语法,简化指针调用 for (auto iterator = ptrCharacterTurnOrderArray.begin(); iterator != ptrCharacterTurnOrderArray.end(); iterator++) { CharacterBase* currentChar = *iterator; engineFeedback += "\n Name: " + currentChar->getCharacterName() + " Initiative: " + std::to_string(currentChar->getCharacterInitiative()) + " Player Character Flag: " + std::to_string(currentChar->getIsPlayerCharacter()); currentChar->setCharacterTurnOrder(iterator - ptrCharacterTurnOrderArray.begin() + 1); engineFeedback += "\nTurn Order: " + std::to_string(currentChar->getCharacterTurnOrder()); } } CharacterBase::CharacterBase() {} double CharacterBase::getCharacterInitiative() const { return cInitiative; } void CharacterBase::setCharacterInitiative(double sInitiative) { cInitiative = sInitiative; } int CharacterBase::getCharacterTurnOrder() const { return cTurnOrder; } void CharacterBase::setCharacterTurnOrder(int sTurnOrder) { cTurnOrder = sTurnOrder; } // 修正成员变量定义位置,放入类内部 double CharacterBase::cInitiative; int CharacterBase::cTurnOrder;
额外说明
- 类成员变量
cInitiative和cTurnOrder需放在CharacterBase类内部,避免成为全局变量,符合类封装逻辑。 - 遍历容器时,先将
*iterator赋值给指针变量(如currentChar),可简化代码,避免重复写(*iterator)->。 - 字符串拼接使用
+=比+更高效,减少临时对象创建。
内容的提问来源于stack exchange,提问作者Strom
相关产品推荐
相关产品推荐

