Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Неправильная работа деструктора 
:(
    Опции темы
Mr_Nuke
Дата 6.4.2007, 21:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 101
Регистрация: 6.4.2007

Репутация: нет
Всего: нет



Собственно проблема такая. 
Дана следующая программа:

Код

#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <iostream.h>

//Класс описывает строку, память выделяется динамически, имеется два конструктора, диструктор

class str
{ char *s;
int n;
public:
str(){n=0;s=NULL;}
str(char *st)
{s=new char [sizeof(st)];
strcpy(s,st);
}


//Функция суммирует два объекта класса Str, результат записывает в S

void form(str x, str y)
{
s= new char [((sizeof x.s) + (sizeof y.s))];
char *t1=NULL;int n1=0;
for (t1=y.s; *t1!='\t';t1++, n1++);
n1--;
strcpy (s, x.s);
strcpy (s+n1, y.s);
}

//печать и диструктор

void print()
{printf ("\n");
for (char *i=s; *i!='\t'; i++)
printf ("%c", *i);
}

~str()
{delete s;
s=NULL; n=0;
}
};


//Главная программа. Диструктор вызывается не явно, однако всетаки вызывается именно данный диструктор, а не стандартный. 

void main()
{ str X ("abs");
   str Y ("123456");
   str Z;
   Z.form(X,Y);
}


----------------------------------

Суть Проблемы: 
Происходит суммирование, результат записывается в Z, Однако информация, находившая в X и Y потеряна. Вместо нее записаны какие то символы.

Испробовано: 
  • Заменить строку "void form(str x, str y)" на "void form (str &x, str &y)", тоесть работать не с копиями переменных, а с самими перменными. Проблема исчезла.
  • Убрали Диструктор. Проблема Исчезла.
Вопрос: 
Почему возникает такая проблема, и какими еще способами ее можно исправить.


Исходник приведен ниже
[*]

Заранее спасибо!



M
chipset
Тег [code=cpp] рулез форева.
СУВ, Chipset.


Присоединённый файл ( Кол-во скачиваний: 3 )
Присоединённый файл  TEST.CPP 0,75 Kb
PM MAIL   Вверх
zkv
Дата 6.4.2007, 21:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Участник Клуба
Сообщений: 2133
Регистрация: 23.7.2006
Где: Санкт-Петербург

Репутация: 26
Всего: 92



для начала, это неверно
Цитата(Mr_Nuke @  6.4.2007,  21:38 Найти цитируемый пост)
s= new char [((sizeof x.s) + (sizeof y.s))];

правильно:
s= new char [ strlen( x.s ) +  strlen( y.s) ];
пардон, вернее так:
s= new char [ strlen( x.s ) +  strlen( y.s)  + 1];
Цитата

Заменить строку "void form(str x, str y)" на "void form (str &x, str &y)", тоесть работать не с копиями переменных, а с самими перменными. Проблема исчезла.

пользуетесь динамической памятью, а конструктор копирования не нарисовали
Цитата

Убрали Диструктор. Проблема Исчезла.

повезло просто скорее всего. 

Это сообщение отредактировал(а) zkv - 6.4.2007, 21:54
PM MAIL   Вверх
Mr_Nuke
Дата 6.4.2007, 22:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 101
Регистрация: 6.4.2007

Репутация: нет
Всего: нет



я не так давно начал изучать Объектно ориентированное... не объяснишь про конструктор копирования пару сторк? 
PM MAIL   Вверх
Damarus
Дата 6.4.2007, 22:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Awaiting Authorisation
Сообщений: 671
Регистрация: 6.5.2006

Репутация: 6
Всего: 29



Цитата(Mr_Nuke @  6.4.2007,  21:38 Найти цитируемый пост)
s=new char [sizeof(st)];

sizeof(st) обычно будет 4.

PM MAIL ICQ Jabber   Вверх
zkv
Дата 6.4.2007, 22:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Участник Клуба
Сообщений: 2133
Регистрация: 23.7.2006
Где: Санкт-Петербург

Репутация: 26
Всего: 92



Цитата(Mr_Nuke @  6.4.2007,  22:14 Найти цитируемый пост)
про конструктор копирования пару сторк?  

при передаче в функцию объекта по значению создается копия объекта (есть еще пара таких случаев ;-)), для этого вызывается конструктор копирования, если пользователь не определил этот самый конструктор, то его  создает сам компилятор. 
Конструктор копирования по умолчанию (вроде так он называется), просто копирует значения всех членов-данных. 
У тебя в этом случае копируется указатель на строку, а не сама строка, те объект в памяти остается один, а указатель на него копируется, что может привести к неприятным последствиям, если ты обратишься к этому объекту после вызова деструктора хотя бы в одном из объектов. 
Скорее всего не это привело к ошибке в твоей программе, там и без этого интересностей хватает smile

Например:
Цитата(Mr_Nuke @  6.4.2007,  21:38 Найти цитируемый пост)
for (t1=y.s; *t1!='\t';t1++, n1++);

видимо вместо '\t' ты имел ввиду '\0'? Наверное длину строки определял? Это можно сделать функцией strlen(). 

Да, в твоем случае конструктор копирования должен выглядеть примерно так:
Код

str( const str &obStr )
{
  n=obStr.n;//или this->n = obStr.n; далее можно также через this
  s= new char[ n + 1];
  strcpy( s,  obStr.s ); 
}


Хотя надо еще исправить этот косяк:

Цитата(Mr_Nuke @  6.4.2007,  21:38 Найти цитируемый пост)
str(char *st)
{s=new char [sizeof(st)];

на
Код

str( const char *st )
{
  n = strlen( st );
  s=new char [ n + 1 ];
  strcpy( s, st );  
}


Еще советую научиться нормально оформлять код (невозможно читать, место экономишь?), и выбирать более осмысленные имена идентификаторам. Ну еще неплохо сразу научить себя разделять объявление класса и реализацию его методов.
   Удачи!

Это сообщение отредактировал(а) zkv - 6.4.2007, 22:47
PM MAIL   Вверх
threef
Дата 7.4.2007, 00:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 375
Регистрация: 27.10.2005
Где: Запорожье

Репутация: 9
Всего: 10



не забудь поправит деструктор 
Код

...
  delete [] s; 
 
иначе будет утечка памяти.
  delete s;
освобождает память размером с один символ 
PM MAIL   Вверх
Daevaorn
Дата 7.4.2007, 01:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2155
Регистрация: 29.11.2004
Где: Москва

Репутация: 51
Всего: 70



Цитата(threef @  7.4.2007,  01:24 Найти цитируемый пост)
освобождает память размером с один символ 

не хочу быть особо въедливым, но это совсем не факт. в большинстве случаев удалится всё-таки вся память, а вот с вызовом деструкторов будут проблемы. а вообще это UB
PM MAIL WWW   Вверх
Xenon
Дата 7.4.2007, 01:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1529
Регистрация: 12.4.2006

Репутация: 11
Всего: 50



Daevaorn, это просто UB без каких-либо предположений smile


--------------------
user posted image  
PM MAIL   Вверх
Mr_Nuke
Дата 7.4.2007, 10:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 101
Регистрация: 6.4.2007

Репутация: нет
Всего: нет



Код

for (t1=y.s; *t1!='\t';t1++, n1++); 
видимо вместо '\t' ты имел ввиду '\0'? Наверное длину строки определял? Это можно сделать функцией strlen(). 


Да, определял я действительно длинну строки. Ток когда я смотрел через debug-watch, в конце строки почему то стояло '\t'

На счет оформления кода - скопировал пост с сайта, где до этого размещал свою задачку.... там сайт автоматом делал вот такое вот выравнивание. Я тут первый раз, и как то не пришло в голову, что тут по другому. Поэтому и прикрепил cpp файл.  

и что такое UB?

На счет остальных советов - буду сидеть, разбираться. Отпишусь, если будет что непонятно. Всем огромное спасибо!

PM MAIL   Вверх
Daevaorn
Дата 7.4.2007, 10:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2155
Регистрация: 29.11.2004
Где: Москва

Репутация: 51
Всего: 70



Цитата(Mr_Nuke @  7.4.2007,  11:09 Найти цитируемый пост)
и что такое UB?

http://en.wikipedia.org/wiki/Undefined_behavior
PM MAIL WWW   Вверх
Mr_Nuke
Дата 7.4.2007, 16:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 101
Регистрация: 6.4.2007

Репутация: нет
Всего: нет



И еще один вопросик. Что делает "const"?
Чем отличается "str(char *st)" от "str( const char *st )" ?
PM MAIL   Вверх
vinter
Дата 7.4.2007, 20:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 13
Всего: 56



Цитата(Mr_Nuke @  7.4.2007,  16:55 Найти цитируемый пост)
И еще один вопросик. Что делает "const"?

оно делает как раз то, что это слово означает smile , а именно делает строку(в данном случае) константной


--------------------
Мой блог
PM MAIL WWW   Вверх
bsa
Дата 7.4.2007, 21:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Цитата(Mr_Nuke @ 7.4.2007,  16:55)
И еще один вопросик. Что делает "const"?
Чем отличается "str(char *st)" от "str( const char *st )" ?

Это больше касается качества кода. Т.е. объявляя функцию с константным указателем или ссылкой в качестве параметра, ты гарантируешь всем, кто ее использует (а так же компилятору, который компилирует твой код), что ты не изменяешь переменную, на которую указывает указатель или ссылка. Другими словами, если ты по ошибке напишешь это:
Код
int str(const char *st) {
...
     st[10] = '\0';
...
}
То компилятор тебя пошлет. А если напишешь так:
Код
int str(char *st) {
...
     st[10] = '\0';
...
}
То компилятор не пискнет.

Больше того, у методов классов тоже есть модификатор const, который означает, что данный метод не меняет аттрибуты класса.
По мимо всего прочего, данные модификаторы помогают при написании программы.
Например, ты пишешь класс, у которого есть метод size():
Код
class MyClass {
...
    unsigned size() const;
...
};
По идее, он не должен менять содержимое класса, а просто должен посчитать занимаемый данными объем памяти. Ты его реализовал, но компилятор выдал кучу ругательств... И ты выясняешь, что где-то в куче кода, банально перепутал источник с приемником (например). Т.е. ты выловил ошибку на этапе компиляции. А отлов отладчиком занимает намного больше времени.
PM   Вверх
Mr_Nuke
Дата 8.4.2007, 19:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 101
Регистрация: 6.4.2007

Репутация: нет
Всего: нет



Все супер! все работает!  smile 
остался последний вопрос: про конструктор копирования.

Код

str( const str &obStr )
{
  this->n=obStr.n;
  s= new char[ n + 1];
  strcpy( s,  obStr.s );
}


первая строчка "&obStr". все слово является какой то переменной или str - это имя класса? если так, то почему оно с большой буквы? 
Или это указатель на копируемый объект?
PM MAIL   Вверх
zkv
Дата 8.4.2007, 19:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Участник Клуба
Сообщений: 2133
Регистрация: 23.7.2006
Где: Санкт-Петербург

Репутация: 26
Всего: 92



Цитата(Mr_Nuke @  8.4.2007,  19:11 Найти цитируемый пост)
первая строчка "&obStr". все слово является какой то переменной или str - это имя класса? если так, то почему оно с большой буквы? 

obStr - это идентификатор (типа object класса str
знак & - указывает, что объект передается по ссылке. По значению объект в конструктор копирования не передать, так как для этого надо вызвать конструктор копирования smile, поэтому передаем его по ссылке, а модификатор const говорит о том,  что мы обещаем его не менять внутри ;-)
Цитата(Mr_Nuke @  8.4.2007,  19:11 Найти цитируемый пост)
то почему оно с большой буквы

ну так захотелось smile
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0959 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.