You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将引用函数转为指针函数出错,求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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 08:10:28