【问题标题】:C++ vector erase method delete my objectC++ 矢量擦除方法删除我的对象
【发布时间】:2017-02-21 23:06:52
【问题描述】:

我首先从向量中获取一个对象 A,然后我调用擦除方法来销毁向量中的该对象,因为我不再需要它了。但是,从调试器中,我发现我在调用erase方法之前得到的对象A也被破坏了。我不明白,因为我认为我得到的是该对象的副本,而擦除方法应该与我的对象 A 无关。

代码

班级单位

头文件

#ifndef UNIT_H
#define UNIT_H
#include <iostream>

class Unit
{
protected:
    int id;

public:
    Unit::Unit(int num = -1);
    virtual ~Unit() = default;
    virtual int getID();

};

#endif

CPP 文件

#include "Unit.h"

Unit::Unit(int num)
{
    id = num;
}

int Unit::getID()
{
    return id;

}

类框

头文件

#ifndef BOX_H
#define BOX_H
#include <string>
#include <iostream>
#include "Unit.h"

class Box : public Unit
{
private:
    std::string* type;
    int* val;
public:
    Box::Box();
    ~Box();
    int getVal();
    std::string getName();
    int getID() override;
};

    #endif

CPP 文件

#include <time.h>
#include "Box.h"

Box::Box() : Unit(5)
{
    int tmp = rand() % 3;
    if (tmp == 0)
    {
        type = new std::string("hp");  // health cur
        val = new int(rand() % 10 + 1);
    }
    else if (tmp == 1)
    {
        type = new std::string("exp");  // skill level or health max
        val = new int(rand() % 5 + 1);
    }
    else
    {
        type = new std::string("punish");  // minus health cur
        val = new int(-1);
    }
}

Box::~Box()
{
    delete type;
    delete val;
}

int Box::getVal()
{
    return *val;
}

std::string Box::getName()
{
    return *type;
}

int Box::getID()
{
    return id;
}

主文件

using namespace std;
int main()
{
    Box test;
    std::vector<Box> bag;
    bag.push_back(test);

    Box tmp = bag[0];

    bag.erase(bag.begin() + 0);

    cout << tmp.getVal();

    system("pause");
    return 0;
}

下面是调试器的截图,因为我没有10个声望,所以不能直接显示。

before

after

如你所见,Box类的“type”和“val”数据成员被修改了。

【问题讨论】:

  • 根据不完整的信息很难确定,但我的第一个猜测是您的复制构造函数没有正确复制。
  • @JerryCoffin。从调试器中,我可以看到副本是正确的,因为对象 tmp 具有正确的所有数据成员。擦除矢量“包”中的元素后,一切都变了。我不明白。矢量“bag”中的元素不是指针。
  • -17891602 在十六进制显示中转换为 0xFEEEFEEE。这是调用HeapFree 后调试堆分配的值(例如,参见this answer)。这是一个强烈的迹象,表明该对象确实被清除了。但是,根据提供的信息,我们无法诊断问题。请提供minimal reproducible example
  • @JerryCoffin 是对的——显然。 1. 不要使用指针和原始newdelete。 2. 见:stackoverflow.com/questions/4172722/what-is-the-rule-of-three
  • “那么我应该如何解决这个问题?” - 停止使用指针作为类成员。没有理由使用int*std::string*。只需使对象成为类成员,您无需执行任何其他操作(好吧,您需要删除 d'tor 主体)。

标签: c++ c++11 vector abstract-class erase


【解决方案1】:

查看此页面以了解索引调用的返回类型

http://en.cppreference.com/w/cpp/container/vector/operator_at

我相信你可能有一个参考,而不是一个不同的对象。

【讨论】:

  • 那我如何获得该对象的副本?
  • 如果此时:Box tmp = bag[index]; 类型名 Box 不涉及引用,则 tmp 不是引用。
  • 您的“Box tmp = ...”可能是 Box& 吗?我只是在猜测,因为你说它是抽象的,所以这意味着很难实例化一个。如果您有办法按照@Pavel 的建议显示更多代码,我敢打赌我们会很清楚。
  • 类型名称不涉及引用是什么意思?
  • @JohnGriffin 我想做的是从向量中获取一个副本,我只使用运算符 []。我使用了一个简单的示例,将 Box 替换为内置类型 int,但它没有显示它是一个引用。
猜你喜欢
  • 2012-06-19
  • 2013-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-03
  • 2020-04-09
相关资源
最近更新 更多