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

对象池与基类赋值操作是否属于C++未定义行为?

老式MMORPG源码中对象池与派生类赋值的疑问

我正在研究一款老式MMORPG的源码,以了解过去的游戏开发实现方式,遇到了一段逻辑如下的简化模拟代码(省略了池类部分):

class VMAIN
{
public:
    int nVar1;
    int nVar2;
    VMAIN():nVar1(0),nVar2(0){;}
    virtual ~VMAIN (){;}
    void Reset()
    {
        nVar1=0;
        nVar2=0;
    }
    void Assign(const VMAIN& vSub)
    {
        *this = vSub;
    }
    VMAIN* GetMAIN(){return this;}
};
class VSUB: public VMAIN
{
public:
    float fVar1;
    float fVar2;
    VSUB():fVar1(0),fVar2(0){;}
    void Reset()
    {
        fVar1 = 0;
        fVar2 = 0;
    };
};
std::queue<VMAIN*> vecMain;
std::queue<VSUB*> vecSub;
VMAIN* NEW_VMAIN()
{
    VMAIN* pMain;
    if ( vecMain.empty() )
    {
        pMain = new VMAIN;
    }
    else
    {
        pMain = vecMain.front();
        vecMain.pop();
    }
    return pMain;
}
VSUB* NEW_SUB()
{
    VSUB* pMain = NULL;
    if ( vecSub.empty() )
    {
        pMain = new VSUB;
    }
    else
    {
        pMain = vecSub.front();
        vecMain.pop();
    }
    return pMain;
}
void RELEASE_MAIN(VMAIN* pMain)
{
    pMain->Reset();
    vecMain.push(pMain);
}
void RELEASE_SUB(VSUB* vSub)
{
    vSub->Reset();
    vecSub.push(vSub);
}
int main()
{
    std::queue<VSUB*>vSub;
    for ( int i = 0; i != 5 ; i++)
    {
        VMAIN* pMain = NEW_VMAIN();
        pMain->nVar1 = i+1;
        pMain->nVar2 = i+1;
        VSUB* pSub = NEW_SUB();
        pSub->Assign(*pMain);
        pSub->fVar1 = float(i)+0.5f;
        pSub->fVar2 = float(i)+0.5f;
        printf("Iteration: %d , nVar1 %d , nVar1 %d, fVar1 %.2f, fVar2 %.2f\n",i,pSub->nVar1,pSub->nVar2,pSub->fVar1,pSub->fVar2);
        vSub.push(pSub);
    }
    printf("\n Releasing \n \n");
    const int nSize = vSub.size();
    for ( int i = 0; i < nSize; i++)
    {
        VSUB* pSub = vSub.front();
        vSub.pop();
        printf("Iteration[Before]: %d , nVar1 %d , nVar1 %d, fVar1 %.2f, fVar2 %.2f\n",i,pSub->nVar1,pSub->nVar2,pSub->fVar1,pSub->fVar2);
        int j = i+10;
        VMAIN* pMain= NEW_VMAIN();
        pMain->nVar1 = j;
        pMain->nVar2 = j;
        if ( j  < 12 )
        {
            RELEASE_MAIN(pSub->GetMAIN());
            pSub->Assign(*pMain);
            printf("Iteration[After Replacing BASE]: %d , nVar1 %d , nVar1 %d, fVar1 %.2f, fVar2 %.2f\n",i,pSub->nVar1,pSub->nVar2,pSub->fVar1,pSub->fVar2);
        }
        else
        {
            RELEASE_MAIN(pMain);
            printf("Iteration[After Not Toching Base Values]: %d , nVar1 %d , nVar1 %d, fVar1 %.2f, fVar2 %.2f\n",i,pSub->nVar1,pSub->nVar2,pSub->fVar1,pSub->fVar2);
        }
        RELEASE_SUB(pSub);
        RELEASE_MAIN(pSub->GetMAIN());
        printf("Iteration[After Release]: %d , nVar1 %d , nVar1 %d, fVar1 %.2f, fVar2 %.2f\n\n",i,pSub->nVar1,pSub->nVar2,pSub->fVar1,pSub->fVar2);
    }
    int nSizeMain = vecMain.size(),nSizeSub = vecSub.size();
    printf("Size of vecMain %d, Size of vecSub %d\n",nSizeMain,nSizeSub);
}

我理解这段代码的逻辑是:先计算基类VMAIN的相关值,若符合要求则将其赋值给派生类VSUB,否则将基类对象归还对象池。测试后代码可以正常运行,但我想确认这种实现是依赖C++未定义行为,还是过去游戏开发中常规的实践方式?


核心结论

这段代码的核心逻辑(基类赋值给派生类的基类成员、对象池复用)符合C++标准,不属于未定义行为,但代码中存在明显的逻辑bug,这些bug不属于老式游戏开发的常规正确实践。

细节分析

1. 代码中的明确bug(非未定义行为,属于逻辑错误)

  • NEW_SUB()函数中,从vecSub队列取对象时,错误调用了vecMain.pop(),这会导致vecMain队列被错误修改,后续对象池的复用逻辑完全混乱。
  • main函数末尾同时调用RELEASE_SUB(pSub)和RELEASE_MAIN(pSub->GetMAIN()),相当于把同一个VSUB对象同时放入vecSub和vecMain两个对象池,后续取出使用时会出现类型不匹配、重复释放等严重问题。

2. 符合C++标准的部分(无未定义行为)

  • 基类VMAIN的Assign函数中使用*this = vSub;:当this指向派生类VSUB对象时,基类赋值运算符只会复制基类部分的成员,派生类成员不受影响,这是C++的标准行为(赋值运算符不支持多态,只会调用当前类型的赋值逻辑)。由于代码中派生类未重写赋值运算符,因此这里的操作完全合法。
  • GetMAIN()返回this:对于VSUB对象来说,这是合法的向上转型(派生类指针转基类指针),属于C++标准允许的操作。

3. 老式MMORPG的常规实践

  • 对象池复用:这是老式MMORPG中非常普遍的性能优化手段,因为服务器需要处理大量频繁创建销毁的对象(如玩家、怪物、技能实例),用对象池避免内存碎片和频繁分配开销是常规操作。
  • 基类/派生类分池管理:为不同类型的对象分别维护对象池,避免类型混淆,是合理的设计思路,但你的代码中出现了把派生类对象放入基类池的错误操作,这不是正确的实践。
  • 封装赋值操作:用Assign函数封装赋值逻辑,而非直接使用赋值运算符,在老代码中很常见,目的是统一控制赋值行为,方便后续扩展(如添加校验、日志)。

内容的提问来源于stack exchange,提问作者Azriel Elijay

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 07:30:51