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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> перегрузка операций 
V
    Опции темы
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   Вверх
Страницы: (3) Все 1 [2] 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
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.0933 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


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

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