-4

I first get an object A from the vector, then I call the erase method to destroy that object in my vector because I don't need it anymore. However, from the debugger, I found that the object A I got before calling erase method is also destroyed. I don't understand that because I thought that what I got is a copy of that object and erase method should have nothing to do with my object A.

Code

Class Unit

Header file

#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 file

#include "Unit.h"

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

int Unit::getID()
{
    return id;

}

Class Box

Header file

#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 file

#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;
}

main file

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;
}

Below is the screenshot from the debugger and because I don't have 10 reputations, I can't display it directly.

before

after

As you can see, the "type" and "val" data member of class Box is modified.

bolov
  • 72,283
  • 15
  • 145
  • 224
kluo
  • 131
  • 1
  • 10
  • 7
    Hard to be sure based on incomplete information, but my first guess would be that you have a copy constructor that's not copying correctly. – Jerry Coffin Oct 13 '16 at 00:54
  • @JerryCoffin. From the debugger, I can see that the copy is correct because object tmp has all the data member correctly. After erasing the element in the vector "bag", everything changed. I don't understand that. Elements in vector "bag" are not pointer. – kluo Oct 13 '16 at 01:00
  • 2
    `-17891602` translates to `0xFEEEFEEE` in hexadecimal display. That's the value assigned by the debug heap after `HeapFree` was called (see [this answer](http://stackoverflow.com/a/353606/1889329), for example). That's a strong indication, that the object was indeed purged. With the information provided, there's nothing we can do to diagnose the issue, though. Please provide a [mcve]. – IInspectable Oct 13 '16 at 01:09
  • 2 lines of code with **no** definitions is not enough. – Galik Oct 13 '16 at 01:14
  • Please reopen my question, during the time off, I was editing my question. – kluo Oct 13 '16 at 01:32
  • Your assignment/copy constructor is not correct. When you a get the element from the vector you get a copy and when you erase it from the vector the destructor is called invalidating your pointers. – MrTux Oct 13 '16 at 01:35
  • @MrTux You mean "Box tmp = bag[0] " ? Why is that – kluo Oct 13 '16 at 01:36
  • `type` and `val` is pointer, the generized copy constructor doesn't perform deep copy, `tmp` is copied from `bag[0]`, but `type` and `val` is still pointing to the same thing. When `bag[0]` being destroyed, `type` and `val` in `tmp` become dangled. – songyuanyao Oct 13 '16 at 01:37
  • 1
    @JerryCoffin was right - obviously. 1. Don't use pointer and raw `new` and `delete`. 2. see: http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three – Pixelchemist Oct 13 '16 at 01:37
  • @songyuanyao I see what you mean. So how should I fix this? – kluo Oct 13 '16 at 01:38
  • It appears that @JerryCoffin had the best guess with a bad copy constructor. You are copying raw pointers. – John Griffin Oct 13 '16 at 01:39
  • @Pixelchemist I'm learning pointers and memory management, so what should I do to fix this while keep these pointers? – kluo Oct 13 '16 at 01:40
  • @kevinnnluo If you want to perform deep copy, you have to write copy ctor and operator by yourself. See the link Pixelchemist posted form more infomations. – songyuanyao Oct 13 '16 at 01:40
  • 2
    *"So how should I fix this?"* - Stop using pointers as class members. There is no reason for an `int*` or a `std::string*`. Simply make the objects class members, and you don't have to do anything else (well, you need to remove the d'tor body). – IInspectable Oct 13 '16 at 01:54
  • Please don't put the answer in the question. Here we have a clear distinction between questions and answers. If you want, you can post an answer to your question. I've rolled back your "add solution" edit. – bolov Oct 13 '16 at 08:43
  • @bolov Ok. Sorry about that. – kluo Oct 13 '16 at 10:59
  • @kevinnnluo Don't worry about it. You'll learn the ropes as you go. – bolov Oct 13 '16 at 11:09

1 Answers1

0

Check out this page about the return type from the index call

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

I believe that you may have a reference, not a different object.

John Griffin
  • 377
  • 2
  • 8
  • Then how do I get a copy of that object? – kluo Oct 13 '16 at 01:03
  • If at this point: `Box tmp = bag[index];` the typename `Box` doesn't involve a reference, then `tmp`isn't a reference. – Pixelchemist Oct 13 '16 at 01:05
  • 1
    Is your "Box tmp = ..." perhaps a Box&? I'm just guessing because you said it was abstract, so that means it's pretty hard to instantiate one. If you have a way to show more code as @Pavel suggested, I'll bet that it becomes clear to us. – John Griffin Oct 13 '16 at 01:06
  • What do you mean by the type name doesn't involved a reference? – kluo Oct 13 '16 at 01:08
  • @JohnGriffin What I wanna do is to get a copy from the vector and I just use the operator []. I use a simple example by replacing Box to built-in type int and it didn't show that it is a reference. – kluo Oct 13 '16 at 01:11
  • The code is too much to show. Otherwise, I would post it. – kluo Oct 13 '16 at 01:11
  • @kevinnnluo: Reduce it until you have the minimal code that still exhibits the problematic behaviour. – Pixelchemist Oct 13 '16 at 01:12
  • @Pixelchemist is absolutely right that your code (only 2 lines by the way) indicates a type Box and I would assume that it is not abstract as he does, except that you say that it is. If Box is not a typedef for a reference type, The Box will get a copy. Check the 'this' pointer of tmp in your debugger against the 'this' pointer in the vector at [index]. And of course, perhaps your assessment of what is happening is unclear. How about some more Box information for us? – John Griffin Oct 13 '16 at 01:17