Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Деструктор не изменяет состояние потока


Автор: Nitro89 8.1.2006, 19:43
Вообщем, пытаясь выполнить упражнение Бьерна Страуструпа, я написал такой код.
Код

class A
{
public:
A() { std::cout<<"Initialization.\n"; }
~A() { std::cout<<"Destroing.\n"; }
};
A a;
int main()
{
std::cout<<"Work.";
return 0;
}

И почему в результате выполнения программы, я увидел только две строчки, а не три, т.е. я увидел только "Initialization." и "Work.". Куда третья делась, ведь деструктор класса A полюбому вызывается. Может, std::cout уничтожается до того, как уничтожится a?
Объясните пожалуйста.

Автор: TIGERоX 8.1.2006, 20:05
пройдитесь дебугером все нормально деструктор вызывается при выходе объекта за предел видимости если вы поставил например getch перед return ток конечно в консоли ничего не увидите потомучто она уже спрячется перед тем как вызывется деструктор smile

Автор: chipset 8.1.2006, 21:55
Компилятор?

Автор: Mephistopheles 9.1.2006, 10:29
По-моему переменную типа A надо объявить в функции main.

Автор: chipset 9.1.2006, 11:00
Это глобальная переменная а вот кажеться компилятор я узнаю -- BCB smile Он любит такое учудить, интересно с какого перепоя его писали...

Автор: Nitro89 9.1.2006, 19:55
Цитата(chipset @ 9.1.2006, 11:00 Найти цитируемый пост)

Это глобальная переменная а вот кажеться компилятор я узнаю -- BCB  Он любит такое учудить, интересно с какого перепоя его писали...

Э нее браток, обознался. MS Visual C++ 6.0....

Автор: threef 9.1.2006, 21:31
Цитата

Код

~A() { std::cout<<"Destroing.\n";

     

добавь

std::cout.flush();

Ну уж очень навороченный cout. Он такой оптимизированный !
Лучше бы setlocale к нему прикрутили smile

Автор: Hearse 9.1.2006, 22:05
Прикол в том, что код инициализации/завершения вызывает CRT, посему вызов деструктора A происходит после того, как функция main вернет управление.
Код

class A
{
public:
A() { std::cout<<"Initialization.\n"; }
~A() { std::cout<<"Destroing.\n"; }
};

int main()
{
    {
         A a;
         
         std::cout<<"Work." ; 
    }

     return 0;
}

Вот такой код покажет все как ты хотел увидеть.

Автор: blackofe 9.1.2006, 22:58
Hearse

в main() можно и без дополнительных скобок обойтись. вот так тоже будет работать:

Код

int main()
{
    A a;

    std::cout << "Work." << endl; 

    return 0;
}


а вот с изначальным кодом вопрос интересный. у меня (vc++ 7.1.3088) такой код

Код

#include <iostream>

class A {
public:
    A()            {    std::cout << "Initialization." << endl; }
    ~A()        {    std::cout << "Destroing." << endl; }
};

A a;

int main()
{
    std::cout << "Work." << endl; 

    return 0;
}


выдал

Код

Initialization.
Work.
Destroing.
Press any key to continue


так что, мне кажется, что в подобном случае порядок уничтожения глобальных объектов неопределен. и разные компилеры это могут делать по-разному. а что в данном случает "глобальнее" - А или cout - я бы не взялся решить smile.

Автор: Void 9.1.2006, 23:06
Цитата(threef @ 9.1.2006, 23:31 Найти цитируемый пост)
Лучше бы setlocale к нему прикрутили

Здрасьте. А imbue что такое?

Автор: Hearse 9.1.2006, 23:22
blackofe Момент вызова завершающего кода CRT не определяется стандартом, например в Mingw/GCC 3.4.2 выводится только две строчки.
Об'являя же 'а' в блоке {} можно быть уверенным, что деструктор вызовется до завершения main().

Автор: blackofe 10.1.2006, 01:04
читаем стандарт:

3.6.1.4

Calling the function
void exit(int);

declared in <cstdlib> (18.3) terminates the program without leaving the current block and hence without destroying any objects with automatic storage duration (12.4). If exit is called to end a program during the destruction of an object with static storage duration, the program has undefined behavior.

3.6.1.5

A return statement in main has the effect of leaving the main function (destroying any objects with automatic storage duration) and calling exit with the return value as the argument. If control reaches the end of main without encountering a return statement, the effect is that of executing
return 0;

так что, вполне в соответствии со стандартом вот такой код

Код
#include <iostream>

class A {
public:
    A()            {    std::cout << "Initialization." << endl; }
    ~A()        {    std::cout << "Destroing." << endl; }
};

int main()
{
    A a;

    std::cout << "Work." << endl; 

    return 0;
}


должен вывести

Код

Initialization.
Work.
Destroing.


а вот такой

Код
#include <iostream>

class A {
public:
    A()            {    std::cout << "Initialization." << endl; }
    ~A()        {    std::cout << "Destroing." << endl; }
};

int main()
{
    A a;

    std::cout << "Work." << endl; 

    exit(0);

    return 0;
}


должен вывести:

Код

Initialization.
Work.


и, кстати говоря, VC++ 7.1 именно так и работает. и нигде в стандарте не написано, что выход из функции main является implementation-defined.

ну, а Mingw/GCC 3.4.2 с его нестрогим следованием стандарту придется засунуть.. куда-нибудь.. ;)

можно сказать больше. вот такой код

Код
#include <iostream>

class A {
public:
    A()            {    std::cout << "Initialization." << endl; }
    ~A()        {    std::cout << "Destroing." << endl; }
};

int main()
{
    A a;

    std::cout << "Work." << endl; 
}


также выведет

Код

Initialization.
Work.
Destroing.


и опять таки в соответствии со стандартом (последнее предложение 3.6.1.5).

Автор: Hearse 10.1.2006, 01:23
blackofe Сорри, проглядел - GCC сразу закрывает консоль , просто мне думалось, что он разрушает консоль после return, и не дает вывести "Destroing"

такой код все прекрасно показывает
Код


#include <iostream>

#include <conio.h>

using namespace std;

class A {
public:
    A()            {    std::cout << "Initialization." << endl; }
    ~A()        {    std::cout << "Destroing." << endl; getch(); }
};

A a;

int main()
{
    std::cout << "Work." << endl; 
    return 0;
}

З.Ы. Про станарт и CRT я имел в виду что не определяется порядок разрушение консоли-разрушение об'ектов.

Автор: threef 10.1.2006, 16:42
blackofe
С твоими обьяснениями завершения функции main никак не вяжется простейший пример
Код

class A
{
public:
A() { printf("Initialization.\n");}
~A() {printf("Destroing\n");}
};
A a;
void main()
{
std::cout<<"work.";
}



Обьект 'a' преспокойненько разрушается, так что exit() тут ни при чем. И CRT нормально продолжает отрабатывать(stdout существует). Все дело в cout, если проверить, то его состояние
good() становится вовсе не good:

~A() {printf("Destroing %d\n",std::cout.good());}

голобальные обьекты создаются ДО main, разрушаются после,

и даже использование внутри main exit() не меняет ситуации

Код

class A
{
public:
A() { printf("Initialization.\n");}
~A() {printf("Destroing.\n");}
};
A a;
int main()
{
std::cout<<"work.\n";
exit(3);
return 0;
}



результат -
Код

Initializatiion.
work.
Destroying.



Автор: blackofe 10.1.2006, 21:26
threef
почему же не вяжется? мы с Hearse'ом обсуждали, нужны ли внутри функции main скобки, чтобы быть уверенным, что деструктор объекта, объявленного внутри функции main, нормально отработает по завершению работы. и мы узнали из стандарта, что все произойдет вполне миленько, если пользоваться return'ом, и нужно быть осторожным при использовании exit().

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

Код

3.6.1.1.
Note: in a freestanding environment, start-up and termination is implementation-defined;
startup contains the execution of constructors for objects of namespace scope with static
storage duration; termination contains the execution of destructors for objects with static
storage duration.


и что умрет раньше - объект a или cout - никто не гарантирует. если программа, откомпиленная твоим конкретнымм компилятором, вывела строку

Код
Destroying.


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

прошу поправить меня, если я чего напутал или понял неправильно.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)