сбой при удалении члена char * в деструкторе собственного контейнера с использованием вектора

до этого я справлялся, здесь я пытаюсь создать свой собственный контейнерный класс, используя vector. Мне это нужно для моей работы. я использую кодовые блоки 10.05

class myclass
{
public :
vector<myclass> array;
char * classname;
...

Проблема в том, что мои данные моего класса хорошо отображается на экране, если его удаление не происходит в деструкторе. Моя функция show () отображает нечетные символы, если я удаляю имя класса. Я полагаю, что это происходит из моего метода построения объекта, и вопрос диапазона, когда я передаю их в качестве аргумента.

 myclass::~myclass()
{
//if(classname) delete [] classname;
}

И вот как это инициализируется в конструктор:

 myclass::myclass(long lvl = 0, const char name[] = "undefined")
:ID(++ ID_counter)
{
level = lvl;

int namelength = strlen(name);
classname = new char[namelength + 1];
strcpy(classname, name);
}

add_content (const myclass & с) предполагается сделать копию элементов c.array и «push_back» их в массиве this->
Я случайно выяснил, что мы можем поместить объект без имени в качестве параметра: mycontainer.add_content (MyClass (3,5));
это работает, но я скептически отношусь к объему, который должен иметь

> int main()
>     {
>        myclass mycontainer(0);
>        mycontainer.add_content(myclass(3,5));
>     ...

Вот полный код:

#include <vector>
#include <iostream>
using namespace std;

class myclass
{
public :

vector<myclass> array;
static long ID_counter;
long ID;
long level;
char * classname;

myclass(int n, long lvl, const char name[]); //push_back n elements, lvl = 0, name = "undefined"myclass(long lvl, const char name[]); //lvl = 0, name = "undefined"myclass::~myclass();

void set_level(long lvl); //recursive function, go down the tree
void add(int n); //push_back n elements
void add(const myclass & c); //push_back and set back the levels
void add_content(const myclass & c); //push_back all the c.array[i] and set back the levels

void show();

template <typename T> myclass & operator[](const T it){ return array[it]; }
};

long myclass::ID_counter = 0;

myclass::myclass(long lvl = 0, const char name[] = "undefined")
:ID(++ ID_counter)
{
level = lvl;

int namelength = strlen(name);
classname = new char[namelength + 1];
strcpy(classname, name);
}
myclass::myclass(int n, long lvl, const char name[] = "undefined")
:ID(++ ID_counter)
{
level = lvl;

int namelength = strlen(name);
classname = new char[namelength + 1];
strcpy(classname, name);

for(int i = 0; i < n; i++) array.push_back( myclass(this->level + 1) );
}
myclass::~myclass()
{
//if(classname) delete [] classname; //there is the point !
}

void myclass::add(int n = 1)
{
for(int i = 0; i < n; i++) array.push_back( myclass(level + 1) );
}

void myclass::add(const myclass & c)
{
array.push_back(c);
array[array.size() - 1].set_level(level + 1);
}

void myclass::add_content(const myclass & c)
{
for(int i = 0; i < c.array.size(); i++)
{
array.push_back(c.array[i]);
array[array.size() - 1].set_level(level + 1);
}
}

void myclass::set_level(long lvl)
{
level = lvl;
for(int i = 0; i < array.size(); i++) array[i].set_level(level + 1);
}

void myclass::show()
{
cout << "ID : " << ID << "\tLvl : " << level << "\t Classname : " << classname << endl;
}

int main()
{
myclass mycontainer(0); //ground level
mycontainer.add_content(myclass(3,5)); //the 3 elements level 5 should be reset to 0+1

mycontainer.show();

for(int i = 0; i < mycontainer.array.size(); i++)
{
mycontainer[i].show();

for(int j= 0; j < mycontainer[i].array.size(); j++)
mycontainer[i][j].show();
}
cout << "\ncheckpoint\n";
system("PAUSE"); //press any key to crash!
return 0;
}

Вот нет удаления * имя класса в деструкторе, программа разрисовывает это:

ID : 1  Lvl : 0  Classname : undefined
ID : 3  Lvl : 1  Classname : undefined
ID : 4  Lvl : 1  Classname : undefined
ID : 5  Lvl : 1  Classname : undefined

checkpoint
Appuyez sur une touche pour continuer...

с удалением и некоторые плохие персонажи появляются с треском:

ID : 1  Lvl : 0  Classname : undefined
ID : 3  Lvl : 1  Classname : ░(?
ID : 4  Lvl : 1  Classname : ░(?
ID : 5  Lvl : 1  Classname : ░(?

checkpoint
Appuyez sur une touche pour continuer...

Process returned -1073741819 (0xC0000005)   execution time : 29.651 s
Press any key to continue.

Я пытался изучить некоторые принципы аргументов и указателей, но этот язык слишком эмпирический и не имеет смысла. Спасибо за помощь.

2

Решение

У вас есть необработанный указатель, и вы не определили конструктор копирования или оператор присваивания. Это означает, что вы получаете автоматически сгенерированные версии, то, что вам не нужно. Просмотрите Правило Трех.

Решение № 1: Реализуйте правильный конструктор копирования и оператор присваивания.

Решение № 2: Изменить char * classname в std::string classname, Теперь автоматически сгенерированный конструктор копирования и оператор присваивания будут работать. Дополнительное преимущество: вам не нужно использовать newвам не нужно использовать delete,

7

Другие решения

Вы должны определить конструктор копирования.

Мой отладчик выдает ошибку здесь:

for(int i = 0; i < n; i++) array.push_back( myclass(this->level + 1) );

мы видим здесь, что новый объект myclass создается, затем копируется (клонируется) в array, тогда оригинал уничтожается, как и любая локальная переменная.

Итак, у нас есть два экземпляра с одним и тем же указателем: один уничтожен, другой внутри array, созданный по умолчанию конструктор копирования, который копирует только необработанную память. Итак, экземпляр внутри array недействителен, поскольку деструктор уже был запущен на нем.

КОД

Следующий дополнительный конструктор решит ситуацию:

myclass::myclass(const myclass& other)
:ID(++ ID_counter)
{
level = other.level;

int namelength = strlen(other.classname);
classname = new char[namelength + 1];
strcpy(classname, other.classname);
}

(выше это то, что называется «конструктор копирования»; да, конечно, вы должны соблюдать «правило трех», чтобы избежать всех потенциальных ошибок)

1

По вопросам рекламы [email protected]