template <typename T>
struct ListNode
{
struct SubNode
{
SubNode(T val,ListNode * parent) : SubNode()
{
if (debug) cout<<"SubNode constructor(T,parent)"<<endl;
this->parent=parent;
*value=val;
}
SubNode(T val) : SubNode()
{
if (debug) cout<<"SubNode constructor(T)"<<endl;
*value=val;
}
SubNode()
{
if (debug) cout<<"SubNode default constructor"<<endl;
next=parent=0;
value=new T();
}
~SubNode()
{
if (debug) cout<<"SubNode destructor"<<endl;
delete value;
}
void debug()
{
if (debug)
cout<<"\n\n-------- DEBUG PRINT -------\nstruct SubNode\nValue="<<*value<<" Value address="<<value<<"\nNext address:"<<next<<"\nParent address:"<<parent<<"\n----------------------------\n\n";
}
T * value;
SubNode * next;
ListNode * parent;
};
ListNode()
{
if (::debug) cout<<"ListNode default constructor"<<endl;
value=new T();
}
ListNode(T val) : ListNode()
{
if (::debug) cout<<"ListNode constructor(T)"<<endl;
*value=val;
}
~ListNode()
{
if (::debug) cout<<"ListNode destructor"<<endl;
delete value;
}
void debug()
{
if (debug)
cout<<"\n\n-------- DEBUG PRINT -------\nstruct ListNode\nValue="<<*value<<" Value address="<<value<<"\nNext address:"<<next<<"\nChild address:"<<child<<"\n----------------------------\n\n";
}
T * value;
ListNode * next;
SubNode * child;
};
template <typename T>
struct SpecialList
{
SpecialList()
{
if (debug) cout<<"SpecialList default constructor"<<endl;
head=new ListNode<T>();
}
SpecialList(T val)
{
if (debug) cout<<"SpecialList constructor(val)"<<endl;
head=new ListNode<T>(val);
}
~SpecialList()
{
ListNode<T> * temp;
for (ListNode<T> * current=head; head->next!=0;)
{
if (current->next!=0) temp=current->next;
cout<<"Delete element "<<current<<"\n";
delete current;
current=temp;
}
}
ListNode<T> * head;
};
Имеются ли тут какие-то ошибки?
Как создать SubNode
ListNode::SubNode <int> ошибка, не получается.
Как проверить код на утечки памяти и "не красивые" места(стат.анализ)?
Может быть уже готовые структуры для этого, скажем в stl или boost, лучше первое конечно.
Лучше value везде хранить по указателю или же по значению? Делаю по указателю чтобы при копировании, например предавая в какой либо метод, или в качестве value выступает класс какой-нибудь, чтобы реже происхдило копирование этого объекта
Спасибо за ответы
Сразу бросается в глаза попытка вызвать один коструктор из другого, например:
SubNode(T val,ListNode * parent) : SubNode()
Так вызывается конструктор класса-предка, а перегруженный конструктор так вызвать не получится.
Еще нашел ошибку здесь:
next=parent=0;
parent и next — это указатели на разные типы (оператор присваивания parent=0 возврщает указатель на ListNode, а присваивать это дело пытается SubNode)
Пока что все, что могу сказать.
Здравствуйте, r1der, Вы писали:
R>R>template <typename T>
R>struct ListNode
R>{
R> struct SubNode
R> {
R> SubNode(T val,ListNode * parent) : SubNode()
R> {
R> if (debug) cout<<"SubNode constructor(T,parent)"<<endl;
this->>parent=parent;
R> *value=val;
R> }
R> SubNode(T val) : SubNode()
R> {
R> if (debug) cout<<"SubNode constructor(T)"<<endl;
R> *value=val;
R> }
R> SubNode()
R> {
R> if (debug) cout<<"SubNode default constructor"<<endl;
R> next=parent=0;
R> value=new T();
R> }
R> ~SubNode()
R> {
R> if (debug) cout<<"SubNode destructor"<<endl;
R> delete value;
R> }
R> void debug()
R> {
R> if (debug)
R> cout<<"\n\n-------- DEBUG PRINT -------\nstruct SubNode\nValue="<<*value<<" Value address="<<value<<"\nNext address:"<<next<<"\nParent address:"<<parent<<"\n----------------------------\n\n";
R> }
R> T * value;
R> SubNode * next;
R> ListNode * parent;
R> };
R> ListNode()
R> {
R> if (::debug) cout<<"ListNode default constructor"<<endl;
R> value=new T();
R> }
R> ListNode(T val) : ListNode()
R> {
R> if (::debug) cout<<"ListNode constructor(T)"<<endl;
R> *value=val;
R> }
R> ~ListNode()
R> {
R> if (::debug) cout<<"ListNode destructor"<<endl;
R> delete value;
R> }
R> void debug()
R> {
R> if (debug)
R> cout<<"\n\n-------- DEBUG PRINT -------\nstruct ListNode\nValue="<<*value<<" Value address="<<value<<"\nNext address:"<<next<<"\nChild address:"<<child<<"\n----------------------------\n\n";
R> }
R> T * value;
R> ListNode * next;
R> SubNode * child;
R>};
R>template <typename T>
R>struct SpecialList
R>{
R> SpecialList()
R> {
R> if (debug) cout<<"SpecialList default constructor"<<endl;
R> head=new ListNode<T>();
R> }
R> SpecialList(T val)
R> {
R> if (debug) cout<<"SpecialList constructor(val)"<<endl;
R> head=new ListNode<T>(val);
R> }
R> ~SpecialList()
R> {
R> ListNode<T> * temp;
R> for (ListNode<T> * current=head; head->next!=0;)
R> {
R> if (current->next!=0) temp=current->next;
R> cout<<"Delete element "<<current<<"\n";
R> delete current;
R> current=temp;
R> }
R> }
R> ListNode<T> * head;
R>};
R>
R>Имеются ли тут какие-то ошибки?
R>Как создать SubNode
R>ListNode::SubNode <int> ошибка, не получается.
R>Как проверить код на утечки памяти и "не красивые" места(стат.анализ)?
R>Может быть уже готовые структуры для этого, скажем в stl или boost, лучше первое конечно.
R>Лучше value везде хранить по указателю или же по значению? Делаю по указателю чтобы при копировании, например предавая в какой либо метод, или в качестве value выступает класс какой-нибудь, чтобы реже происхдило копирование этого объекта
R>Спасибо за ответы
Здравствуйте, r1der, Вы писали:
комментарии в коде:
R>R>template <typename T>
R>struct ListNode
R>{
R> struct SubNode
R> {
/*
R> SubNode(T val,ListNode * parent) // error can't compile: SubNode()
R> {
R> if (debug) cout<<"SubNode constructor(T,parent)"<<endl;
this->>parent=parent;
R> *value=val;
R> }
R> SubNode(T val) // error can't compile: SubNode()
R> {
R> if (debug) cout<<"SubNode constructor(T)"<<endl;
R> *value=val;
R> }
R> SubNode()
R> {
R> if (debug) cout<<"SubNode default constructor"<<endl;
R> next=parent=0;
R> value=new T();
R> }
*/ // то же самое одной строчкой
SubNode(const T &val = T(),ListNode * par = NULL)
: value(new T(val)),
parent(par),
next(NULL)
{
if (debug) cout<<"SubNode constructor(T,parent)"<<endl;
}
R> ~SubNode()
R> {
R> if (debug) cout<<"SubNode destructor"<<endl;
R> delete value;
R> }
R> void debug()
R> {
R> if (debug)
R> cout<<"\n\n-------- DEBUG PRINT -------\nstruct SubNode\nValue="<<*value<<" Value address="<<value<<"\nNext address:"<<next<<"\nParent address:"<<parent<<"\n----------------------------\n\n";
R> }
R> T * value;
R> SubNode * next;
R> ListNode * parent;
R> };
// то же самое с этими конструкторами
/*
R> ListNode()
R> {
R> if (::debug) cout<<"ListNode default constructor"<<endl;
R> value=new T();
R> }
R> ListNode(T val) // error can't compile: ListNode()
R> {
R> if (::debug) cout<<"ListNode constructor(T)"<<endl;
R> *value=val;
R> }
*/
R> ~ListNode()
R> {
R> if (::debug) cout<<"ListNode destructor"<<endl;
R> delete value;
R> }
R> void debug()
R> {
R> if (debug)
R> cout<<"\n\n-------- DEBUG PRINT -------\nstruct ListNode\nValue="<<*value<<" Value address="<<value<<"\nNext address:"<<next<<"\nChild address:"<<child<<"\n----------------------------\n\n";
R> }
R> T * value;
R> ListNode * next;
R> SubNode * child;
R>};
R>template <typename T>
R>struct SpecialList
R>{
R> SpecialList()
R> {
R> if (debug) cout<<"SpecialList default constructor"<<endl;
R> head=new ListNode<T>();
R> }
R> SpecialList(T val)
R> {
R> if (debug) cout<<"SpecialList constructor(val)"<<endl;
R> head=new ListNode<T>(val);
R> }
R> ~SpecialList()
R> {
R> //ListNode<T> * temp;
R> for (ListNode<T> * current=head; current != NULL;)
/*head->next!=0 */ // удалил и сразу пошел по указателю...
R> {
ListNode<T> * temp;
R> /*if (current->next!=0)*/ // зачем эта проверка?
temp=current->next;
R> cout<<"Delete element "<<current<<"\n";
R> delete current;
//кто будет удалять SubNode? это оставлю реализовать тебе :user:
//а что если несколько ListNode/SubNode будут указывать на один и тот же SubNode? :crash:
R> current=temp;
R> }
R> }
R> ListNode<T> * head;
R>};
R>
R>Имеются ли тут какие-то ошибки?
да
Здравствуйте, Caracrist, Вы писали:
C>Здравствуйте, r1der, Вы писали:
C>комментарии в коде:
R>>R>>template <typename T>
R>>struct ListNode
R>>{
R>> struct SubNode
R>> {
C>/*
R>> SubNode(T val,ListNode * parent) // error can't compile: SubNode()
R>> {
R>> if (debug) cout<<"SubNode constructor(T,parent)"<<endl;
this->>>parent=parent;
R>> *value=val;
R>> }
R>> SubNode(T val) // error can't compile: SubNode()
R>> {
R>> if (debug) cout<<"SubNode constructor(T)"<<endl;
R>> *value=val;
R>> }
R>> SubNode()
R>> {
R>> if (debug) cout<<"SubNode default constructor"<<endl;
R>> next=parent=0;
R>> value=new T();
R>> }
C>*/ // то же самое одной строчкой
C> SubNode(const T &val = T(),ListNode * par = NULL)
C> : value(new T(val)),
C> parent(par),
C> next(NULL)
C> {
C> if (debug) cout<<"SubNode constructor(T,parent)"<<endl;
C> }
R>> ~SubNode()
R>> {
R>> if (debug) cout<<"SubNode destructor"<<endl;
R>> delete value;
R>> }
R>> void debug()
R>> {
R>> if (debug)
R>> cout<<"\n\n-------- DEBUG PRINT -------\nstruct SubNode\nValue="<<*value<<" Value address="<<value<<"\nNext address:"<<next<<"\nParent address:"<<parent<<"\n----------------------------\n\n";
R>> }
R>> T * value;
R>> SubNode * next;
R>> ListNode * parent;
R>> };
C>// то же самое с этими конструкторами
C>/*
R>> ListNode()
R>> {
R>> if (::debug) cout<<"ListNode default constructor"<<endl;
R>> value=new T();
R>> }
R>> ListNode(T val) // error can't compile: ListNode()
R>> {
R>> if (::debug) cout<<"ListNode constructor(T)"<<endl;
R>> *value=val;
R>> }
C>*/
R>> ~ListNode()
R>> {
R>> if (::debug) cout<<"ListNode destructor"<<endl;
R>> delete value;
R>> }
R>> void debug()
R>> {
R>> if (debug)
R>> cout<<"\n\n-------- DEBUG PRINT -------\nstruct ListNode\nValue="<<*value<<" Value address="<<value<<"\nNext address:"<<next<<"\nChild address:"<<child<<"\n----------------------------\n\n";
R>> }
R>> T * value;
R>> ListNode * next;
R>> SubNode * child;
R>>};
R>>template <typename T>
R>>struct SpecialList
R>>{
R>> SpecialList()
R>> {
R>> if (debug) cout<<"SpecialList default constructor"<<endl;
R>> head=new ListNode<T>();
R>> }
R>> SpecialList(T val)
R>> {
R>> if (debug) cout<<"SpecialList constructor(val)"<<endl;
R>> head=new ListNode<T>(val);
R>> }
R>> ~SpecialList()
R>> {
R>> //ListNode<T> * temp;
R>> for (ListNode<T> * current=head; current != NULL;)
C>/*head->next!=0 */ // удалил и сразу пошел по указателю...
R>> {
C> ListNode<T> * temp;
R>> /*if (current->next!=0)*/ // зачем эта проверка?
C> temp=current->next;
R>> cout<<"Delete element "<<current<<"\n";
R>> delete current;
C>//кто будет удалять SubNode? это оставлю реализовать тебе :user:
C>//а что если несколько ListNode/SubNode будут указывать на один и тот же SubNode? :crash:
R>> current=temp;
R>> }
R>> }
R>> ListNode<T> * head;
R>>};
R>>
R>>Имеются ли тут какие-то ошибки?
C>да
Спасибо за указанные ошибки, теперь структуры выглядят вот так:
const int debug=1;
template <typename T>
struct SubNode
{
SubNode(T val)
{
if (::debug) cout<<"SubNode constructor(T)"<<endl;
next=0;
value=new T();
*value=val;
}
SubNode()
{
if (::debug) cout<<"SubNode default constructor"<<endl;
next=0;
value=new T();
}
~SubNode()
{
if (::debug) cout<<"SubNode destructor"<<endl;
delete value;
}
void debug()
{
if (::debug)
cout<<"\n\n-------- DEBUG PRINT -------\nstruct SubNode\nValue="<<*value<<" Value address="<<value<<"\nNext address:"<<next<<"\n----------------------------\n\n";
}
T * value;
SubNode * next;
};
template <typename T,typename A>
struct ListNode
{
ListNode()
{
if (::debug) cout<<"ListNode default constructor"<<endl;
value=new T();
next=0;
child=0;
}
ListNode(T val)
{
if (::debug) cout<<"ListNode constructor(T)"<<endl;
value=new T(val);
next=0;
child=0;
}
~ListNode()
{
if (::debug) cout<<"ListNode destructor"<<endl;
delete value;
}
void debug()
{
if (::debug)
cout<<"\n\n-------- DEBUG PRINT -------\nstruct ListNode\nValue="<<*value<<" Value address="<<value<<"\nNext address:"<<next<<"\nChild address:"<<child<<"\n----------------------------\n\n";
}
T * value;
ListNode * next;
SubNode<A> * child;
};
template <typename T,typename A>
struct SpecialList
{
SpecialList()
{
if (debug) cout<<"SpecialList default constructor"<<endl;
head=new ListNode<T,A>();
}
SpecialList(T val)
{
if (debug) cout<<"SpecialList constructor(val)"<<endl;
head=new ListNode<T,A>(val);
}
bool AddNode(T val)
{
ListNode<T,A> * n=head;
head=new ListNode<T,A>(val);
head->next=n;
return true;
}
bool DeleteNode(bool delete_head=0)
{
if ((!delete_head && head->next==0) or !head) return false;
ListNode<T,A> * to_delete=head;
head=head->next;
if (to_delete->child)
{
SubNode<A> * curr, *temp;
for (curr=to_delete->child; curr!=0;)
{
temp=curr->next;
cout<<"Delete subitem "<<*(curr->value)<<endl;
delete curr;
curr=temp;
}
}else delete to_delete;
return true;
}
bool AddSubNode(int num,A data)
{
ListNode<T,A> * temp;
int counter=0;
for (temp=head;temp!=0;temp=temp->next,++counter)
if (counter==num) break;
if (temp) {
if (::debug) cout<<"AddSubNode as "<<num<<" element\n";
SubNode<A> * t=new SubNode<A>(data);
if (temp->child)
{
SubNode<A> * curr;
for (curr=temp->child; curr->next!=0; curr=curr->next);
curr->next=t;
return true;
}else {
temp->child=t;
return true;
}
}else return false;
}
~SpecialList()
{
while(DeleteNode(true));
}
void Print()
{
int i=0;
cout<<"\n\n-------- LIST PRINT ---------\n";
for (ListNode<T,A> * current=head;current!=0;current=current->next,++i)
{
cout<<"Node "<<i<<" Value="<<*(current->value)<<endl;
if (current->child!=0)
{
SubNode<A> * temp;
cout<<"SubNodes: ";
for (temp=current->child;temp!=0;temp=temp->next)
cout<<*(temp->value)<<" ";
cout<<"\n";
}else cout<<"Not child\n";
cout<<"\n";
}
cout<<"------------------------------\n\n";
}
ListNode<T,A> * head;
};
Но стоит вот какая задача, надо сделать SpecialList<строка 4 символа, строка 4 символа>
Не знаю как лучше реализовать, приходит вот такие решения
1) SpecialList<char *, char *> list("test")
Это неверно, но оно компилируется. Какой в итоге образуется ListNode?
Во что превращается T * value; из ListNode,в char ** value? Но как он тогда создается строкой value=new T(val);
что в данном случае происодит? Указатель на указатель инициализируется новым указателем на указатель временного объекта "test" в динамической памяти или же все таки создается в динамической памяти "test" и T здесь не ** а просто *
2) Special<string,string> не знаю как это будет работать по отношению к памяти, что здесь будет временным объектом, что будет создаваться. Полагаю что внутри в динамической памяти будет создавтаь новый объект стринг и туда будет копироваться значение временного стринга, но ведь стринг внутри и так работает на указателях?
3) SpecialList<char [],char []> Но тогда придется как-то поменять конструктор ListNode, чтобы тот умел сздавать и обычные объекты и массивы, как это сделать ума не приложу
cout<<typeid(list.head->value).name(); для первого случая показывает загадочное PPc, наверное намекает на то что это пипец))
И как ту можно использовать RTTI и dynamic_case для определения типа list.head->value?
Заранее большое спасибо за ответы.
Здравствуйте, r1der, Вы писали:
R>Спасибо за указанные ошибки, теперь структуры выглядят вот так:
http://codepad.org/fkyfZMAE — я не досчитался одного деструктора
код нужно проверять, и не на форуме...
Здравствуйте, Caracrist, Вы писали:
C>Здравствуйте, r1der, Вы писали:
R>>Спасибо за указанные ошибки, теперь структуры выглядят вот так:
C>http://codepad.org/fkyfZMAE — я не досчитался одного деструктора
C>код нужно проверять, и не на форуме...
хм странно, деструкторы все на месте
~SpecialList()
{
while(DeleteNode(true));
}
~SubNode()
{
if (::debug) cout<<"SubNode destructor"<<endl;
delete value;
}
~ListNode()
{
if (::debug) cout<<"ListNode destructor"<<endl;
delete value;
}
а где тогда и как проверять?