erkus
erkus

Reputation: 69

I get an error when trying to make a vector of classes inside of the same class

I am trying to make a class with decendants of the same class, to make a tree, but when i try to access something insode of the vector it never works. i get an exception: std::length_error when trying to access the string.

#include <iostream>
#include <vector>
#include <string>

using namespace std;

class A {
  public:
  string name;
  vector<A*> children;
};

int main()
{
    A cl;
    cl.name= "HI!";
    for(int i = 0; i < 10;i++) {
        A newCl;
        newCl.name= "World!";
        cl.children.push_back(&newCl);
    }

    for(int i = 0; i < 10;i++) {
        // error here:
        cout << cl.children[i]->name << endl;
    }

    return 0;
}

Anybody know an easier way to make a tree in C++, or how to fix this?

Upvotes: 3

Views: 108

Answers (2)

The problem is in this loop

for(int i = 0; i < 10;i++) {
        A newCl;
        newCl.name= "World!";
        cl.children.push_back(&newCl);
}

The variable newCl will cease to exist at the end of the iteration and you are inserting its address in the vector. When you access it, you are accessing a dangling pointer, this is undefined behavior and your program can crash, produce garbage or anything in between.

You can use heap allocation as proposed by Oblivion, but in such a case you might want to consider the use of smart pointers for memory management.

Otherwise, you can have a vector of values std::vector<A> instead of pointers, possible from C++17 (for more details, see: How can I declare a member vector of the same class?)

Edit: I clarified the use of std::vector<A> after Chipster's comment.

Upvotes: 6

Oblivion
Oblivion

Reputation: 7374

You store reference to a temporary as children:

A newCl; 
newCl.name= "World!";
cl.children.push_back(&newCl);

Once you are out of scope the children will dangle.

A* newCl = new A;

Should fix. But you have to go through the vector to free your children.

If you had a reason to use pointers, it is better to use smart pointers:

vector<shared_ptr<A>> children;

Live

Upvotes: 1

Related Questions