【问题标题】:Lambda function capture by copy results in corruped dataLambda 函数通过复制捕获导致数据损坏
【发布时间】:2016-06-30 10:57:40
【问题描述】:
std::vector<Spell*> playerSpells{ new Jump(1), new Arrow() };   

for (int i = 0; i < playerSpells.size(); i++)
{
    player->addSpell(playerSpells[i]);
}

for (int i = 0; i < player->getSpells().size(); i++)
{
    auto spell = player->getSpells()[i];

    player->getSpells()[i]->icon->onClickEndEH.add([=]() {
        auto a = player->getSpells()[i];
        auto b = player->getSpells()[i]->sprite;
    });
}

首先,我检查了spell 变量,它的字段已正确初始化。调用 lambda 函数时,变量 b 已损坏。如果这还不够,我可以提供代码的其他部分。

我尽量简化了;

//GAMEOBJECT.H
class GameObject
{
public:
    cocos2d::Sprite* sprite = nullptr;

    GameObject(const std::string fileName = "", bool clickable = false);
    ~GameObject();
};


//GAMEOBJECT.CPP
GameObject::GameObject(const std::string fileName, bool addClickEvent)
{
    if (fileName != "")
    {
        this->sprite = Sprite::create(fileName);
    }
    else
    {
        this->sprite = Sprite::create();
    }

    if (addClickEvent)
    {
        this->addTouchListener();
        this->clickable = true;
    }
}

GameObject::~GameObject()
{
    Director::getInstance()->getEventDispatcher()->removeEventListener(this->listener);
}

//SPELL.H
class Spell : public GameObject
{
public:
    GameObject* icon = nullptr;

    Spell(const std::string fileName = "", bool clickable = false);
    ~Spell();
}

//SPELL.CPP
Spell::Spell(const std::string fileName, bool clickable) : GameObject(fileName, clickable)
{
}

Spell::~Spell()
{
    delete icon;
}

//ARROW.H
class Arrow : public Spell
{
public:
    Arrow();
    ~Arrow();
};

//ARROW.CPP
Arrow::Arrow() : Spell("arrow.png")
{
    this->icon = new GameObject("arrow.png", true);
}

【问题讨论】:

  • 或许,playerSpells 中的指针所指的符咒在调用 lambda 之前就被销毁了?
  • 要么我刚刚中风,要么这不是有效的 C++。 “for each”和“playerSpells 中的自动拼写”看起来像是 Python 和 C++ 的一些奇怪的混蛋。
  • @SamVarshavchik 我认为这与 Visual Studio 有关。我要改变它。但它正在工作。
  • @makadev 你是说这是合规代码吗?我可能也中风了,但这对我来说没有意义。
  • I can provide other parts of the code if that's not enough. 这还不够,但不要提供“代码的其他部分”。而是提供minimal reproducible example

标签: c++ c++11 lambda cocos2d-x


【解决方案1】:

通过添加retain()release() 函数解决了这个问题。我认为 cocos2dx 检查了它的池并删除了精灵,因为它没有被添加到范围内的场景中。

GameObject::GameObject(const std::string fileName, bool addClickEvent)
{
    if (fileName != "")
    {
        this->sprite = Sprite::create(fileName);
    }
    else
    {
        this->sprite = Sprite::create();
    }

    this->sprite->retain();

    if (addClickEvent)
    {
        this->addTouchListener();
        this->clickable = true;
    }
}

GameObject::~GameObject()
{
    this->sprite->release();
    Director::getInstance()->getEventDispatcher()->removeEventListener(this->listener);
}

【讨论】:

    猜你喜欢
    • 2013-11-04
    • 1970-01-01
    • 1970-01-01
    • 2011-04-20
    • 2019-07-24
    • 2011-09-17
    • 2020-10-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多