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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> перегрузка операций 
V
    Опции темы
serendip
Дата 27.1.2006, 02:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Здравствуйте! smile
Кто-нибудь видит что-нибудь нехорошее в этих перегрузках?
Код

DMass::DMass(int m)
{  n=m;
   d=StrToInt(Form2->Edit3->Text);
   a=new float[n];
}
 DMass& DMass::operator=(const DMass &v)
 {
   for (int i=0; i<n; i++)
     a[i]=v.a[i];
      return *this;
 }

 DMass DMass::operator~()const
 { DMass rr(n);
           for (int i=0; i<n; i++)
           rr.a[i]= a[i]-d;
         return rr;
 }
....
DMass x(n);
   ...
     x=~x;

Работает(вторая) совсем непонятно, вадаёт один и тот же неожидаемый рез-т
(1,35244; 1,35244; 0; 0; ...0) И при повторном запуске ошибку(куда-то чего-то не по тому адресу)
PM MAIL ICQ   Вверх
JackYF
Дата 27.1.2006, 03:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

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



что такое DMass?
полный код в студию...

во второй функции не предусмотрено, мне кажется, разных размеров - откуда ты уверен, что они совпадают - опять же таки полный код DMass.

что такое переменная d и чему она равна (или может быть равна?)




--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
threef
Дата 27.1.2006, 11:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата

Код

 DMass& DMass::operator=(const DMass &v)
 {
   for (int i=0; i<n; i++)
     a[i]=v.a[i];
      return *this;
 }





Я думаю здесь:
for (int i=0; i<n; i++)

i<n ?
либо i<v.n
либо
this->resize(v.getsize());

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


Новичок



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

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



Итаак...
Код

class DMass
{    float* a;
        int n;
        float d;
       float step(float,float);
public:
        DMass(int = 1);
       ~DMass();
        void vvod1();
        void vvod2();
        void vivod1();
        void vivod2();
        DMass& operator=(const DMass&) ;
        DMass operator^(const DMass&) const; 
        DMass operator~()const;
};
//---------------------------------------------------------------------------
DMass::DMass(int m)
{  n=m;
   d=StrToFloat(Form2->Edit3->Text);
   a=new float[n];
}

Перегрузка та же. Есть ещё одна перегрузка, но она выдает точно такой же результатsmile
Код

DMass DMass::operator^(const DMass &v)const  
{ DMass f(n);
   for (int i=0; i<n; i++)
         f.a[i]=step(a[i],v.a[i]);

         return f;
}


Размер массивов всегда совпадает(так задумывалось)
Переменная d - просто обычное число, которое нужно вычесть из каждого эл-та массива.
Причём, без перегрузок"^"и"~" пр-мма работает нормально - всё вводит, выводит и даже присваивает объекты (т.е. срабатывает перегр. "=", я надеюсь)
Цитата

Я думаю здесь:
for (int i=0; i<n; i++)

i<n ?
либо i<v.n
либо
this->resize(v.getsize());

- не помогает.
Такая загадка... smile smile[code=cpp]

Это сообщение отредактировал(а) serendip - 27.1.2006, 22:29
PM MAIL ICQ   Вверх
BreakPointMAN
Дата 28.1.2006, 00:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Итак, для начала... smile Твой класс имеет члены-указатели:
Код

class DMass
{    float* a;
...

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

DMass::DMass(int m)
{  n=m;
   d=StrToFloat(Form2->Edit3->Text);
   a=new float[n];
}

Это означает, что должны быть соответствующим образом определены деструктор данного класса, а также конструктор копирования и операция присваивания. В деструкторе ты должен высвобождать выделенную конструктором память (используя delete), а копировать и присваивать объекты данного класса нужно создавая в каждом из них "свои" динамические данные..

Оператор присваивания у тебя уже определен неверно:
Код

 DMass& DMass::operator=(const DMass &v)
 {
   for (int i=0; i<n; i++)
     a[i]=v.a[i];
      return *this;
 }



--------------------
"Разруха не в клозетах, а в головах." © Ф.Ф. Преображенский (М.Булгаков, "Собачье сердце")
PM WWW ICQ   Вверх
serendip
Дата 28.1.2006, 00:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



...ну что вам сказать...smile
ничего не понятно, кроме деструктораsmile
Могу только ответить:"А в учебнике так!":)
Т.е вы хотите сказать, что в "=" нужно создавать ещё один объект?
PM MAIL ICQ   Вверх
BreakPointMAN
Дата 28.1.2006, 00:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(serendip @ 28.1.2006, 00:35 Найти цитируемый пост)

Могу только ответить:"А в учебнике так!":)

Либо в учебнике не так (например, нет выделения памяти с помощью new), либо учебник на свалку... smile
Цитата(serendip @ 28.1.2006, 00:35 Найти цитируемый пост)

Т.е вы хотите сказать, что в "=" нужно создавать ещё один объект?

Т.е. хочу сказать, что сначала нужно немного почитать про копирование и присваивание, конструкторы и деструкторы... smile


--------------------
"Разруха не в клозетах, а в головах." © Ф.Ф. Преображенский (М.Булгаков, "Собачье сердце")
PM WWW ICQ   Вверх
serendip
Дата 28.1.2006, 00:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



smile Не могу уже читать, так меня всё это досталоsmile
Архангельскийsmile
PM MAIL ICQ   Вверх
BreakPointMAN
Дата 28.1.2006, 01:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(serendip @ 28.1.2006, 00:59 Найти цитируемый пост)

Архангельский

Архангельский для изучения среды C++ Builder хорош, но никак не для изучения языка C++... smile А понятия "конструктор", "деструктор" и пр. - это язык... Так что книгу по C++ в руки ... и читать! smile


--------------------
"Разруха не в клозетах, а в головах." © Ф.Ф. Преображенский (М.Булгаков, "Собачье сердце")
PM WWW ICQ   Вверх
serendip
Дата 28.1.2006, 10:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



smile Я в курсе, что такое конструктор и деструктор,
а вот
Цитата

конструктор копирования

и
Цитата

присваивать объекты данного класса нужно создавая в каждом из них "свои" динамические данные..

- не совсем понимаю..Думается мне, что в данном случае в этом нет необходимости.
Но мне очень необходмо понять, почему не работают перегрузки!smile
При объявлении объекта я каждый раз создаю в нём свои динамические данные, разве не так?
PM MAIL ICQ   Вверх
Fin
Дата 28.1.2006, 10:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дракон->Спать();
**


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

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



Скрытая логическая ошибка (в класофикации граблей № 2):
Код

DMass DMass::operator~()const
 { DMass rr(n);
           for (int i=0; i<n; i++)
           rr.a[i]= a[i]-d;
         return rr;
 }


В функции создается статический объект, при выходе из функции объект автоматически уничтожается. И ссылка на него некоретна.


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


Эксперт
****


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

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



Цитата(Fin @ 28.1.2006, 10:42 Найти цитируемый пост)

В функции создается статический объект, при выходе из функции объект автоматически уничтожается. И ссылка на него некоретна.

Приглядись, там нет ссылки.
PM MAIL WWW   Вверх
Fin
Дата 28.1.2006, 10:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дракон->Спать();
**


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

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



Это что return rr Да это не ссылка на объект. Но вывод за пределы функции результатов убитого уже экземпляра объекта.


--------------------
Пролетал мимо.
PM MAIL   Вверх
Daevaorn
Дата 28.1.2006, 11:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Fin
Тогда по твоей логике

Код

int f()
{
   return 123;
}


тоже не коректно?smile
PM MAIL WWW   Вверх
Fin
Дата 28.1.2006, 11:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дракон->Спать();
**


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

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



Коректно. Компилятор скорее всего сделает такую последовательность команд аcсемблера.

Код

   mov ax,7B
   ret


Это сообщение отредактировал(а) Fin - 28.1.2006, 11:13


--------------------
Пролетал мимо.
PM MAIL   Вверх
Daevaorn
Дата 28.1.2006, 11:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Fin
Хе. А в том случае вызовет конструктор копирования. А при большом везении просто соптимизирует.
PM MAIL WWW   Вверх
Fin
Дата 28.1.2006, 11:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дракон->Спать();
**


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

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



Под статический объект в функции отводится память в стэке. При выходе из функции, весь стэк отведенный под функцию возврашается. И дальнейшая ссылка на данную область памяти некоректна.

Это сообщение отредактировал(а) Fin - 28.1.2006, 11:18


--------------------
Пролетал мимо.
PM MAIL   Вверх
Daevaorn
Дата 28.1.2006, 11:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Fin
Никто не спорит. Просто ты забыл, что это С++, а не asm и компилятор занает что делает. Поверь
Добавлено @ 11:20
Цитата(Fin @ 28.1.2006, 11:16 Найти цитируемый пост)

Под статический объект в функции отводится память в стэке

А это совсем не верно. В стеке только локальные не статические переменные.
PM MAIL WWW   Вверх
Fin
Дата 28.1.2006, 11:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дракон->Спать();
**


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

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



Цитата

В стеке только локальные не статические переменные.

Экземпляр объекта можно создать динамически и статически. Для функции статический экземпляр объекта локален. И тут я не вижу в чем не соответствие.

Цитата

Просто ты забыл, что это С++, а не asm и компилятор занает что делает. Поверь

Компилятору как то по барабану, что ты твориш, самое главное синтаксически правильно. Тебе искать глюки. Лучше сразу делать безглючно, чем весь день сидеть и вылавливать их.

Это сообщение отредактировал(а) Fin - 28.1.2006, 11:28


--------------------
Пролетал мимо.
PM MAIL   Вверх
Daevaorn
Дата 28.1.2006, 11:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Fin @ 28.1.2006, 11:27 Найти цитируемый пост)

Для функции статический экземпляр объекта локален

В С++ у панятия статический своё значение, не надо путать.

А глюков там нет

Код

int f()
{
   int a = 777;
   return a;
}


Это же у тебя вопросов не вызвает.
PM MAIL WWW   Вверх
Void
Дата 28.1.2006, 11:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

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



Цитата(Fin @ 28.1.2006, 13:27 Найти цитируемый пост)
Экземпляр объекта можно создать динамически и статически. Для функции статический экземпляр объекта локален. И тут я не вижу в чем не соответствие.

Такое объяснение не соответсвует принятой в C++ терминологии, и вводит в заблуждение. Локальные объекты имеют automatic storage duration, а static storage duration — это совсем другое.

Цитата(Fin @ 28.1.2006, 13:27 Найти цитируемый пост)

Компилятору как то по барабану, что ты твориш, самое главное синтаксически правильно. Тебе искать глюки. Лучше сразу делать безглючно, чем весь день сидеть и вылавливать их.

Ты по-прежнему утверждаешь, что вот такой код:
Код
class A { ... };

A foo() {
    A obj;
    ...
    return obj;
}

Некорректен?


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
Fin
Дата 28.1.2006, 11:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дракон->Спать();
**


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

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



ОК, ребята делайте как хотите. Просто меня иногда достают глюки в неожиданных местах. Поэтому я сразу подстилаю соломку.


--------------------
Пролетал мимо.
PM MAIL   Вверх
Void
Дата 28.1.2006, 12:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

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



Fin
Забавно, а как ты тогда возвращаешь объекты из функций? Исключительно в куче?


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
Fin
Дата 28.1.2006, 13:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дракон->Спать();
**


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

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



Ну чтож, идем к первоисточнику: т.е. к скомпилированному уже коду smile . Условия эксперемента, VC++6.0 Debag режим. Сама программа на С++.
Код

class A {
public:
    A(void) {};
    ~A(void) {};
};

A foo(void)
{
    A obj;
    return obj;
}

int main()
{
    foo();
    return 0;
}


Откомпилированный код, кусок, где идет вызов функции foo
Код

00401138   lea         eax,[ebp-4]
0040113B   push        eax
0040113C   call        @ILT+0(foo) (00401005)
00401141   add         esp,4
00401144   lea         ecx,[ebp-4]
00401147   call        @ILT+10(A::~A) (0040100f)

Первые две строки, в стеке под адрес компилятор зарезервировал место, и передает его через стэк в функцию foo. После вызова функции вызывает деструктор, передавая this объекта через регистр cx.
Сама функция foo
Код

7:    A foo(void)
8:    {                                                       
00401030   push        ebp
00401031   mov         ebp,esp
00401033   push        0FFh
00401035   push        offset __ehhandler$?foo@@YA?AVA@@XZ (00412e57)
0040103A   mov         eax,fs:[00000000]
00401040   push        eax
00401041   mov         dword ptr fs:[0],esp
00401048   sub         esp,48h
0040104B   push        ebx
0040104C   push        esi
0040104D   push        edi
0040104E   lea         edi,[ebp-54h]
00401051   mov         ecx,12h
00401056   mov         eax,0CCCCCCCCh
0040105B   rep stos    dword ptr [edi]
0040105D   mov         dword ptr [ebp-14h],0
9:        A obj;
00401064   lea         ecx,[ebp-10h]
00401067   call        @ILT+5(A::A) (0040100a)
10:       return obj;
0040106C   mov         eax,dword ptr [ebp+8]
0040106F   mov         cl,byte ptr [ebp-10h]
00401072   mov         byte ptr [eax],cl
00401074   mov         edx,dword ptr [ebp-14h]
00401077   or          edx,1
0040107A   mov         dword ptr [ebp-14h],edx
0040107D   lea         ecx,[ebp-10h]
00401080   call        @ILT+10(A::~A) (0040100f)
00401085   mov         eax,dword ptr [ebp+8]
11:   }
00401088   mov         ecx,dword ptr [ebp-0Ch]
0040108B   mov         dword ptr fs:[0],ecx
00401092   pop         edi
00401093   pop         esi
00401094   pop         ebx
00401095   add         esp,54h
00401098   cmp         ebp,esp
0040109A   call        __chkesp (00401550)
0040109F   mov         esp,ebp
004010A1   pop         ebp
004010A2   ret

Парочка коментариев:
Строка по адресу 00401067 идет вызов конструктора.
В адрес [ebp-10h] скидывается ссылка на экземпляр класса (this) Этот адрес находится в стэке самой функции foo.
Строка 0040106F идет копирование инфы с объекта созданного в функции foo в объект созданный в месте, где вызвана функция.
Строка 00401080 Идет вызов деструктора экземпляра, который принадлежит функции foo.
Строка 00401085 Идет возврат адреса экземпляра через регистр ax, который был передан ранее.

Теперь чуть усложним программу.
Код

#include <iostream.h>
class A {
public:
    A(void) {cout << "Constructor " << this << endl;};
    ~A(void) {cout << "Destructor " << this << endl;};
};

A foo(void)
{
    A obj;
    return obj;
}

int main()
{
    A s=foo();
    return 0;
}

Выдаваемый результат:
Цитата

Constructor 0x0012FF10
Destructor 0x0012FF10
Destructor 0x0012FF7C
Press any key to continue

Прошу заметить уважаемую публику, что конструктор для экземпляра с адресом 0x0012FF7C не был вызван. Компилятор пропустил на ура, без проблем.

Это сообщение отредактировал(а) Fin - 28.1.2006, 13:22


--------------------
Пролетал мимо.
PM MAIL   Вверх
BreakPointMAN
Дата 28.1.2006, 13:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(serendip @ 28.1.2006, 10:15 Найти цитируемый пост)

- не совсем понимаю..Думается мне, что в данном случае в этом нет необходимости.

И зря тебе так думается. Даже если в конце-концов твой код заработает, неужели тебе не будет неприятно, что он написан криво?.. А если ты не сделаешь то, что тебе посоветовали, то будешь ловить, в лучшем случае, утечки памяти, либо, в худшем, Access Violation'ы. Тебе оно надо? Думаю, что нет...


--------------------
"Разруха не в клозетах, а в головах." © Ф.Ф. Преображенский (М.Булгаков, "Собачье сердце")
PM WWW ICQ   Вверх
Void
Дата 28.1.2006, 13:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

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



Цитата(Fin @ 28.1.2006, 15:17 Найти цитируемый пост)
Прошу заметить уважаемую публику, что конструктор для экземпляра с адресом 0x0012FF7C не был вызван.

12.8/15
И не ищи проблем на ровном месте.


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
BreakPointMAN
Дата 28.1.2006, 13:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Fin @ 28.1.2006, 13:17 Найти цитируемый пост)

Прошу заметить уважаемую публику, что конструктор для экземпляра с адресом 0x0012FF7C не был вызван. Компилятор пропустил на ура, без проблем.

Конструктор был вызван. Но не конструктор по умолчанию (определенный тобой), а конструктор копирования (созданный неявно).
Если ты задаешь его явно, то увидишь, что конструктор вызывается:
Код

 A(const A&){cout<<"Copy constructor " << this << endl;}



--------------------
"Разруха не в клозетах, а в головах." © Ф.Ф. Преображенский (М.Булгаков, "Собачье сердце")
PM WWW ICQ   Вверх
Fin
Дата 28.1.2006, 13:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дракон->Спать();
**


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

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



Еше чуть усложним класс
Код

#include <iostream.h>
class A {
public:
    A(void); 
    ~A(void); 
protected:
    int ch[25];
};

A::A(void)
{
    cout << "Constructor " << this << " ";
    //ch=new char[25];
    cout << "Adress of ch is " << ch << endl;
}

A::~A(void)
{
    cout << "Destructor  " << this << " ";
    cout << "Adress of ch is " << ch << endl;
    //if (ch !=NULL) delete [] ch;
    //ch=NULL;
}


A foo(void)
{
    A obj;
    return obj;
}

int main()
{
    A s=foo();
    return 0;
}

Получаем результаты:
Цитата

Constructor 0x0012FE50 Adress of ch is 0x0012FE50
Destructor  0x0012FE50 Adress of ch is 0x0012FE50
Destructor  0x0012FF1C Adress of ch is 0x0012FF1C
Press any key to continue


Теперь раскрываем ремы и делаем ch как ссылка.
Код

#include <iostream.h>
class A {
public:
    A(void); 
    ~A(void); 
protected:
    int *ch;
};

A::A(void)
{
    cout << "Constructor " << this << " ";
    ch=new int[25];
    cout << "Adress of ch is " << ch << endl;
}

A::~A(void)
{
    cout << "Destructor  " << this << " ";
    cout << "Adress of ch is " << ch << endl;
    if (ch !=NULL) delete [] ch;
    ch=NULL;
}


A foo(void)
{
    A obj;
    return obj;
}

int main()
{
    A s=foo();
    return 0;
}

Тут же получаем ошибку исполнения. предворительный результат до ошибки:
Цитата

Constructor 0x0012FF10 Adress of ch is 0x00320B00
Destructor  0x0012FF10 Adress of ch is 0x00320B00
Destructor  0x0012FF7C Adress of ch is 0x00320B00


Вывод: таким способом можно пользоваться, если нет в экземпляре объекта динамических выделений памяти.


--------------------
Пролетал мимо.
PM MAIL   Вверх
Daevaorn
Дата 28.1.2006, 14:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Fin @ 28.1.2006, 13:58 Найти цитируемый пост)

Вывод: таким способом можно пользоваться, если нет в экземпляре объекта динамических выделений памяти.

Ну ты прям Америку открыл. Понятно что в таком случае нужно самому писать конструктор копирования и оператор присваивания. Ты отвлекся от первоночалного кода, а то что ты привел ничего не доказывает, кроме как пример не до конца дописанного класса.
PM MAIL WWW   Вверх
BreakPointMAN
Дата 28.1.2006, 14:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



А если бы мы корректно определили конструктор копирования? smile
Как-нибудь так (пишу сгоряча, поэтому могу насажать грубых ляпов...):
Код

A::A(const A& rhs)
   {
    cout<<"Copy constructor "<<this<<endl;
    ch=new int[25];
    for(int i=0; i<25; i++)
       ch[i]=rhs.ch[i];
    cout << "Adress of ch is " << ch << endl;
   }


Так что совет тот же, как и serendip: читай про копирование и присваивание! smile
Добавлено @ 14:15
Кстати, в исходной программе, открывающей данный топик одна из главных проблем как раз в отсутствии копирующего конструктора и заключается... smile


--------------------
"Разруха не в клозетах, а в головах." © Ф.Ф. Преображенский (М.Булгаков, "Собачье сердце")
PM WWW ICQ   Вверх
LPBOY
Дата 28.1.2006, 15:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Цитата(Void @ 28.1.2006, 11:40 Найти цитируемый пост)

Такое объяснение не соответсвует принятой в C++ терминологии, и вводит в заблуждение.
Локальные объекты имеют automatic storage duration, а static storage duration — это совсем другое.

ИМХО немного не так. Локальные объекты это те, которые объявлены в local scope.
Соответственно они могут иметь как automatic storage duration, так и static storage duration.
--------------------
Каждый человек по-своему прав, а по-моему нет...
PM MAIL   Вверх
Void
Дата 28.1.2006, 18:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

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



LPBOY
+1 Сгоряча не оговорил все возможные варианты smile


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
serendip
Дата 28.1.2006, 20:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Ужас какой...smile Пойду читать!smile Спасибо вам большое, честно говоря о конструкторе копирования я услышала от вас впервые..
И действительно, пр-мма вышла за область выделенной памяти и начала уже буквы выводить smile

Забавно..В 1-ом сообщении от BreakPointMAN написано самое главноеsmile
Ну с трудом как-то верилось..smile
Просто я не видела между динамически выделенной памятью и конструктором копирования никакой связи.
Прошу прощенья..smile

Это сообщение отредактировал(а) serendip - 28.1.2006, 20:39
PM MAIL ICQ   Вверх
blackofe
Дата 2.2.2006, 21:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Цитата(Fin @ 28.1.2006, 13:17)
Теперь чуть усложним программу.
Код

#include <iostream.h>
class A {
public:
    A(void) {cout << "Constructor " << this << endl;};
    ~A(void) {cout << "Destructor " << this << endl;};
};

A foo(void)
{
    A obj;
    return obj;
}

int main()
{
    A s=foo();
    return 0;
}

Выдаваемый результат:
Цитата

Constructor 0x0012FF10
Destructor 0x0012FF10
Destructor 0x0012FF7C
Press any key to continue

Прошу заметить уважаемую публику, что конструктор для экземпляра с адресом 0x0012FF7C не был вызван. Компилятор пропустил на ура, без проблем.

доусложним усложненную программу smile:

Код

class A {
public:
    A(void) {cout << "Constructor " << this << endl;};
    A(const A &a)                                {    cout << "copy A()" << this << endl; }
    ~A(void) {cout << "Destructor " << this << endl;};
};

A foo(void)
{
    A obj;
    return obj;
}

int main()
{
    A s=foo();
    return 0;
}


результат:

Код

Constructor 0012FDDB
copy A()0012FED7
Destructor 0012FDDB
Destructor 0012FED7


- была вызвана функция foo, внутри которой был создан объект типа A (первая выведенная запись).

- данный объект был возвращен из функции foo оператором return. при этом используется конструктор копирования, который мы сейчас доопределили явно (у тебя он не был определен, и за тебя его создал компилер) - вторая строчка вывода. обрати внимание - был создан новый объект - совершенно самостоятельный.

- далее - выход из области видимости для первого объекта. для него вызывается деструктор (третья строчка вывода).

- переменная s - и есть наш новый объект, который был создан путем копирования другого объекта, созданного внутри функции foo. при выходе из области видимости (функции main) для этого объекта вызывается деструктор. опять же можно обратить внимание, что деструктор вызывается для объекта, созданного конструктором копии.

так что все правильно. и никакого криминала в возвращении объекта функцией нет.

Это сообщение отредактировал(а) blackofe - 2.2.2006, 21:11
PM MAIL   Вверх
Fin
Дата 3.2.2006, 01:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дракон->Спать();
**


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

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



blackofe Я с этим разобрался. В тот же день я проделал примерно тот же самый код, что и ты привел. Что мы имеем. Двойное создание и копирование класса. При наследовании класса, все время нужно поддерживать конструктор копирования.
И это все благодоря элементарной человеческой лени при написании кода. Я ленив, но не до такой степени.


--------------------
Пролетал мимо.
PM MAIL   Вверх
Void
Дата 3.2.2006, 07:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

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



Fin
Знаешь, это возражения примерно из той же оперы, что и «никогда не пользуйтесь указателями, а то в вашем проекте заведутся маленькие злобные существа — меморилики».
Возвращать класс по значению или на куче — исключительно вопрос семантики данного класса.
Цитата(Fin @ 3.2.2006, 03:39 Найти цитируемый пост)
И это все благодоря элементарной человеческой лени при написании кода.

Элементарная человеческая лень привела к появлению Java и C#, где о таких вещах думать не надо. И это хорошо.


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
Страницы: (3) [Все] 1 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

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

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

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

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


 




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


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

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