как остановить создание класса
От: Аноним  
Дата: 08.09.06 08:27
Оценка:
В конcтрукторе некоторого класса выполняется, например, выделение памяти. Если не удалось выделить память, и следовательно, правильно проинициализировать класс, как лучше всего просигнальть об этом остальному программному коду?
Re: как остановить создание класса
От: kan Великобритания  
Дата: 08.09.06 08:29
Оценка: -1
Аноним wrote:

> В конcтрукторе некоторого класса выполняется, например, выделение

> памяти. Если не удалось выделить память, и следовательно, правильно
> проинициализировать класс, как лучше всего просигнальть об этом
> остальному программному коду?
В исключительных ситуациях обычно кидают исключения.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re: как остановить создание класса
От: Какая разница Украина  
Дата: 08.09.06 08:29
Оценка:
Здравствуйте, Аноним, Вы писали:

А>В конcтрукторе некоторого класса выполняется, например, выделение памяти. Если не удалось выделить память, и следовательно, правильно проинициализировать класс, как лучше всего просигнальть об этом остальному программному коду?


метнуть исключение std::bad_alloc
!0xDEAD
Re[2]: как остановить создание класса
От: Аноним  
Дата: 08.09.06 08:35
Оценка:
Здравствуйте, kan, Вы писали:

kan>Аноним wrote:


>> В конcтрукторе некоторого класса выполняется, например, выделение

>> памяти. Если не удалось выделить память, и следовательно, правильно
>> проинициализировать класс, как лучше всего просигнальть об этом
>> остальному программному коду?
kan>В исключительных ситуациях обычно кидают исключения.

Произошел сбой. Забросили исключение. Перехватили его. И тут вопрос, нужно ли этот непроинициализировавшийся объект удалять: delete something; ?
Re[2]: как остановить создание класса
От: Какая разница Украина  
Дата: 08.09.06 08:36
Оценка:
Здравствуйте, Какая разница, Вы писали:

КР>метнуть исключение std::bad_alloc


хотя зачем оно и так кинется если выделение идет через new
Имхо — ничего не надо делать
!0xDEAD
Re[3]: как остановить создание класса
От: Аноним  
Дата: 08.09.06 08:39
Оценка:
Здравствуйте, Какая разница, Вы писали:

КР>Здравствуйте, Какая разница, Вы писали:


КР>>метнуть исключение std::bad_alloc


КР>хотя зачем оно и так кинется если выделение идет через new

КР>Имхо — ничего не надо делать

Случай с выделение памяти был взят для примера. Имеется ввиду ситуация когда просто не удалось правильно проинициализировать класс.
Re: как остановить создание класса
От: deadlight Россия  
Дата: 08.09.06 08:39
Оценка:
Здравствуйте, Аноним, Вы писали:

А>В конcтрукторе некоторого класса выполняется, например, выделение памяти. Если не удалось выделить память, и следовательно, правильно проинициализировать класс, как лучше всего просигнальть об этом остальному программному коду?


В принципе, можно и без исключения.
1) Функция FinalConstruct — возвращающая код ошибки
2) Умные указатели для объектов, под которые распределяется память, + флажок успеха, к-й проверять в коде использующем класс

Умные указатели рекомендую и для случая с исключением
Re[4]: как остановить создание класса
От: Какая разница Украина  
Дата: 08.09.06 08:43
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Какая разница, Вы писали:


КР>>Здравствуйте, Какая разница, Вы писали:


КР>>>метнуть исключение std::bad_alloc


КР>>хотя зачем оно и так кинется если выделение идет через new

КР>>Имхо — ничего не надо делать

А>Случай с выделение памяти был взят для примера. Имеется ввиду ситуация когда просто не удалось правильно проинициализировать класс.


ну тогда наверное метнуть исключение my_exception которое наследуется от std::exception и на этом
пожалуй в конструкторе ничего больше не надо
!0xDEAD
Re[5]: как остановить создание класса
От: Аноним  
Дата: 08.09.06 08:50
Оценка:
Здравствуйте, Какая разница, Вы писали:

КР>Здравствуйте, Аноним, Вы писали:


А>>Здравствуйте, Какая разница, Вы писали:


КР>>>Здравствуйте, Какая разница, Вы писали:


КР>>>>метнуть исключение std::bad_alloc


КР>>>хотя зачем оно и так кинется если выделение идет через new

КР>>>Имхо — ничего не надо делать

А>>Случай с выделение памяти был взят для примера. Имеется ввиду ситуация когда просто не удалось правильно проинициализировать класс.


КР>ну тогда наверное метнуть исключение my_exception которое наследуется от std::exception и на этом

КР>пожалуй в конструкторе ничего больше не надо

Но остается вопрос, нужно ли этот непроинициализировавшийся класс удалять, например delete something;
(класс создавался динамически)?
Re[3]: как остановить создание класса
От: Aera Беларусь  
Дата: 08.09.06 08:50
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Произошел сбой. Забросили исключение. Перехватили его. И тут вопрос, нужно ли этот непроинициализировавшийся объект удалять: delete something; ?


Если брошено исключение, то для всех переменных которые уже были сконструированы будут вызваны деструкторы


class A
{
  std::string a;
  std::auto_ptr<int> b;
public:
  A()
  : a("")
  , b(new int)  
  {
    throw std::exception();
    // будут вызваны деструкторы для a и для b
  }

  ~A()
  {
    // деструктор никогда не будет вызыван, поскольку конструктор никогда не завершит работу
  }
};

int main()
{
  try 
  {
    std::string bb;
    A a;
  }
  catch(std::exception&)
  {
    // будет вызыван деструктор для bb
  }
}
--
RedApe
Re[6]: как остановить создание класса
От: Какая разница Украина  
Дата: 08.09.06 08:53
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Но остается вопрос, нужно ли этот непроинициализировавшийся класс удалять, например delete something;
А>(класс создавался динамически)?

заворачивай свой new CMyClass() в умный указатель
например хотя бы std::auto_ptr и спи спокойно
Тебя перестанут мучить твои сомнения
!0xDEAD
Re[4]: как остановить создание класса
От: Аноним  
Дата: 08.09.06 08:57
Оценка:
Здравствуйте, Aera, Вы писали:

A>Здравствуйте, Аноним, Вы писали:


А>>Произошел сбой. Забросили исключение. Перехватили его. И тут вопрос, нужно ли этот непроинициализировавшийся объект удалять: delete something; ?


A>Если брошено исключение, то для всех переменных которые уже были сконструированы будут вызваны деструкторы


A>

A>class A
A>{
A>  std::string a;
A>  std::auto_ptr<int> b;
A>public:
A>  A()
A>  : a("")
A>  , b(new int)  
A>  {
A>    throw std::exception();
A>    // будут вызваны деструкторы для a и для b
A>  }

A>  ~A()
A>  {
A>    // деструктор никогда не будет вызыван, поскольку конструктор никогда не завершит работу
A>  }
A>};

A>int main()
A>{
A>  try 
A>  {
A>    std::string bb;
A>    A a;
A>  }
A>  catch(std::exception&)
A>  {
A>    // будет вызыван деструктор для bb
A>  }
A>}

A>


Aera, а если объект создавался динамически?


class A
{
  std::string a;
  std::auto_ptr<int> b;
public:
  A()
  : a("")
  , b(new int)  
  {
    throw std::exception();
    // будут вызваны деструкторы для a и для b
  }

  ~A()
  {
    // деструктор никогда не будет вызыван, поскольку конструктор никогда не завершит работу
  }
};

int main()
{
  A * a;
  try 
  {
    std::string bb;
    a = new A;
  }
  catch(std::exception&)
  {
    // будет вызыван деструктор для bb
    //нужен ли здесь delete a; ?
  }
}
Re[5]: как остановить создание класса
От: Аноним  
Дата: 08.09.06 08:59
Оценка:
Здравствуйте, Какая разница, Вы писали:

КР>Здравствуйте, Аноним, Вы писали:


А>>Здравствуйте, Какая разница, Вы писали:


КР>>>Здравствуйте, Какая разница, Вы писали:


КР>>>>метнуть исключение std::bad_alloc


КР>>>хотя зачем оно и так кинется если выделение идет через new

КР>>>Имхо — ничего не надо делать

А>>Случай с выделение памяти был взят для примера. Имеется ввиду ситуация когда просто не удалось правильно проинициализировать класс.


КР>ну тогда наверное метнуть исключение my_exception которое наследуется от std::exception и на этом

КР>пожалуй в конструкторе ничего больше не надо

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

еще замечание — при ошибки выделения памяти простой new возвращает 0, а не кидает эксепшн
Re: как остановить создание класса
От: chygyrynsky Германия  
Дата: 08.09.06 09:07
Оценка:
A a;
bool bInitialized = a.init();
if (!bInitialized)
{
...
}
Re[6]: как остановить создание класса
От: Какая разница Украина  
Дата: 08.09.06 09:07
Оценка:
Здравствуйте, Аноним, Вы писали:

А>еще замечание — при ошибки выделения памяти простой new возвращает 0, а не кидает эксепшн


не все так делают
Visual C++ например кидается как раз исключением если простой new
Чтобы возвратился NULL нужно new nothrow
!0xDEAD
Re[7]: как остановить создание класса
От: Aera Беларусь  
Дата: 08.09.06 09:10
Оценка:
Здравствуйте, Какая разница, Вы писали:

КР>Здравствуйте, Аноним, Вы писали:

А>>Но остается вопрос, нужно ли этот непроинициализировавшийся класс удалять, например delete something;
А>>(класс создавался динамически)?

КР>заворачивай свой new CMyClass() в умный указатель

КР>например хотя бы std::auto_ptr и спи спокойно
КР>Тебя перестанут мучить твои сомнения

-1

Необходимости думать это не отменяет:

int foo(std::auto_ptr<C>, std::auto_ptr<C>);
int main()
{
  foo(std::auto_ptr<C>(new C()), std::auto_ptr<C>(new C()));
}


Если компилятор решит вызывать сначала два конструктора С, а только затем два конструктора std::auto_ptr<C>, то в случае, если второй конструктор кинет исключение C, получится утечка памяти и не вызыванный деструктор ~C.
--
RedApe
Re[7]: как остановить создание класса
От: Аноним  
Дата: 08.09.06 09:19
Оценка:
Здравствуйте, Какая разница, Вы писали:

КР>Здравствуйте, Аноним, Вы писали:


А>>еще замечание — при ошибки выделения памяти простой new возвращает 0, а не кидает эксепшн


КР>не все так делают

КР>Visual C++ например кидается как раз исключением если простой new
КР>Чтобы возвратился NULL нужно new nothrow

не совсем так.

MSDN: The new and delete Operators

Beginning in Visual C++ .NET 2002, the CRT's new function (in libc.lib, libcd.lib, libcmt.lib, libcmtd.lib, msvcrt.lib, and msvcrtd.lib) will continue to return NULL if memory allocation fails. However, the new function in the Standard C++ Library (in libcp.lib, libcpd.lib, libcpmt.lib, libcpmtd.lib, msvcprt.lib, and msvcprtd.lib) will support the behavior specified in the C++ standard, which is to throw a std::bad_alloc exception if the memory allocation fails.

Normally, if you #include one of the C++ standard headers, like <new>, you'll get a /defaultlib directive in your object that will reference the appropriate C++ Standard Library according to the CRT model you used (the /M* compiler options). Generally, that will cause the linker to use the throwing operator new from the C++ Standard Library instead of the nonthrowing one from the main CRT, because the order of defaultlib directives will cause libcp.lib to be searched before libc.lib (under /ML).


кслову сказать имено потому то

delete 0;

ни чего не делает и является безопасным.

вот.
Re[8]: как остановить создание класса
От: Аноним  
Дата: 08.09.06 09:23
Оценка:
Здравствуйте, Aera, Вы писали:

A>Здравствуйте, Какая разница, Вы писали:


КР>>Здравствуйте, Аноним, Вы писали:

А>>>Но остается вопрос, нужно ли этот непроинициализировавшийся класс удалять, например delete something;
А>>>(класс создавался динамически)?

Если класс грамотно спроектирован — ничего удалять не надо.

КР>>заворачивай свой new CMyClass() в умный указатель

КР>>например хотя бы std::auto_ptr и спи спокойно
КР>>Тебя перестанут мучить твои сомнения

Возможно имелось ввиду заворачивай поля своего класса в RAII-подобные обертки?

A>Необходимости думать это не отменяет:

A>

A>int foo(std::auto_ptr<C>, std::auto_ptr<C>);
A>int main()
A>{
A>  foo(std::auto_ptr<C>(new C()), std::auto_ptr<C>(new C()));
A>}
A>


A>Если компилятор решит вызывать сначала два конструктора С, а только затем два конструктора std::auto_ptr<C>, то в случае, если второй конструктор кинет исключение C, получится утечка памяти и не вызыванный деструктор ~C.


+1

За это еще Майерс в далеком 199* году по рукам бил =)
Пример хрестоматийный. Хотя действительно имеет место быть.
Re[6]: как остановить создание класса
От: chem  
Дата: 08.09.06 09:28
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Но остается вопрос, нужно ли этот непроинициализировавшийся класс удалять, например delete something;

А>(класс создавался динамически)?

При появлении таких вопросов лучшее место для поиска ответа — стандарт. Вот чего пишет наш ISO/IEC 14882 в пункте 15.2, второй абзац (выделение мое):

An object that is partially constructed or partially destroyed will have destructors executed for all of its fully constructed subobjects, that is, for subobjects for which the constructor has completed execution and the destructor has not yet begun execution. Should a constructor for an element of an automatic array throw an exception, only the constructed elements of that array will be destroyed. If the object or array was allocated in a new-expression, the matching deallocation function (3.7.3.2, 5.3.4, 12.5), if any, is called to free the storage occupied by the object.


Т.е. при исключении в конструкторе память будет освобождена автоматически.
Re[8]: как остановить создание класса
От: Aera Беларусь  
Дата: 08.09.06 09:30
Оценка:
Здравствуйте, Аноним, Вы писали:

А>кслову сказать имено потому то

А>delete 0;
А>ни чего не делает и является безопасным.

стандартный "delete 0" ничего не делает, потому что Microsoft что-то там переделала в своей реализации CRT?
--
RedApe
Re[7]: как остановить создание класса
От: Аноним  
Дата: 08.09.06 09:41
Оценка:
Здравствуйте, chem, Вы писали:

C>Здравствуйте, Аноним, Вы писали:


А>>Но остается вопрос, нужно ли этот непроинициализировавшийся класс удалять, например delete something;

А>>(класс создавался динамически)?

C>При появлении таких вопросов лучшее место для поиска ответа — стандарт. Вот чего пишет наш ISO/IEC 14882 в пункте 15.2, второй абзац (выделение мое):


C>

C>An object that is partially constructed or partially destroyed will have destructors executed for all of its fully constructed subobjects, that is, for subobjects for which the constructor has completed execution and the destructor has not yet begun execution. Should a constructor for an element of an automatic array throw an exception, only the constructed elements of that array will be destroyed. If the object or array was allocated in a new-expression, the matching deallocation function (3.7.3.2, 5.3.4, 12.5), if any, is called to free the storage occupied by the object.


C>Т.е. при исключении в конструкторе память будет освобождена автоматически.


опять же, если только не была выделена память (или любые _другие_ ресурсы) в конструкторе ДО исключения. например:


class A {
char* aaa;

A()
{
aaa = new char[1000];

throw runtime_exception("lalal");
}

~A(){}

}

A* = new A();


aaa — НЕ освободится.
Re[5]: как остановить создание класса
От: g_i  
Дата: 08.09.06 09:43
Оценка:
Здравствуйте, Аноним, Вы писали:

Не нужен
Re[9]: как остановить создание класса
От: Аноним  
Дата: 08.09.06 09:45
Оценка:
Здравствуйте, Aera, Вы писали:

A>Здравствуйте, Аноним, Вы писали:


А>>кслову сказать имено потому то

А>>delete 0;
А>>ни чего не делает и является безопасным.

A>стандартный "delete 0" ничего не делает, потому что Microsoft что-то там переделала в своей реализации CRT?


безопасное удаление нулевого указателя это стандард если не ошибаюсь, потому как new (std::nothrow) — это тоже стандард.

вобщем при вызове new всегда нужно быть готовым и к 0 и к эксепшину. эксепшн может быть в любом случае и з конструктора, а 0 — завит от реализации и настроек.
Re[8]: как остановить создание класса
От: chem  
Дата: 08.09.06 09:50
Оценка:
Здравствуйте, Аноним, Вы писали:

C>>Здравствуйте, Аноним, Вы писали:


А>>>Но остается вопрос, нужно ли этот непроинициализировавшийся класс удалять, например delete something;

А>>>(класс создавался динамически)?

C>>Т.е. при исключении в конструкторе память будет освобождена автоматически.


А>опять же, если только не была выделена память (или любые _другие_ ресурсы) в конструкторе ДО исключения. например:


//skipped


А>aaa — НЕ освободится.


Как я понял, спрашивалось насчет памяти, выделенной под объект, конструктор которого кидает исключение. Естественно, что aaa в Вашем примере не освободится.
Re[9]: как остановить создание класса
От: Аноним  
Дата: 08.09.06 10:05
Оценка:
Здравствуйте, chem, Вы писали:

C>Здравствуйте, Аноним, Вы писали:


C>>>Здравствуйте, Аноним, Вы писали:


А>>>>Но остается вопрос, нужно ли этот непроинициализировавшийся класс удалять, например delete something;

А>>>>(класс создавался динамически)?

C>>>Т.е. при исключении в конструкторе память будет освобождена автоматически.


А>>опять же, если только не была выделена память (или любые _другие_ ресурсы) в конструкторе ДО исключения. например:


C>
C>//skipped
C>


А>>aaa — НЕ освободится.


C>Как я понял, спрашивалось насчет памяти, выделенной под объект, конструктор которого кидает исключение. Естественно, что aaa в Вашем примере не освободится.


я просто привел очень простой пример к чему нужно быть готовым. в этом примере именно из конструктора исключение и кидается, но вся память не освобождается. все это может быть на много сложнее. просто надо иметь ввиду, что деструктор в этом случае не вызывается и помнить об этом при написании конструктора.
Re[10]: как остановить создание класса
От: Aera Беларусь  
Дата: 08.09.06 10:08
Оценка:
Здравствуйте, Аноним, Вы писали:

А>вобщем при вызове new всегда нужно быть готовым и к 0 и к эксепшину. эксепшн может быть в любом случае и з конструктора, а 0 — завит от реализации и настроек.


Добавим в скобках: при работе на компиляторах, которые допускают в этом случае несоответствие стандарту — VC++.
--
RedApe
Re[10]: как остановить создание класса
От: chem  
Дата: 08.09.06 10:15
Оценка:
Здравствуйте, Аноним, Вы писали:


A>>стандартный "delete 0" ничего не делает, потому что Microsoft что-то там переделала в своей реализации CRT?


А>безопасное удаление нулевого указателя это стандард если не ошибаюсь, потому как new (std::nothrow) — это тоже стандард.


+1

А>вобщем при вызове new всегда нужно быть готовым и к 0 и к эксепшину. эксепшн может быть в любом случае и з конструктора, а 0 — завит от реализации и настроек.


Не совсем так — если для соотв. operator new не был указан пустой exception-specification, то при сбое в выделении памяти он кидает bad_alloc, а если был указан пустой ( throw() ) — то возвращает null.
Re[11]: как остановить создание класса
От: Аноним  
Дата: 08.09.06 14:56
Оценка:
Здравствуйте, chem, Вы писали:

C>Здравствуйте, Аноним, Вы писали:



A>>>стандартный "delete 0" ничего не делает, потому что Microsoft что-то там переделала в своей реализации CRT?


А>>безопасное удаление нулевого указателя это стандард если не ошибаюсь, потому как new (std::nothrow) — это тоже стандард.


C>+1


А>>вобщем при вызове new всегда нужно быть готовым и к 0 и к эксепшину. эксепшн может быть в любом случае и з конструктора, а 0 — завит от реализации и настроек.


C>Не совсем так — если для соотв. operator new не был указан пустой exception-specification, то при сбое в выделении памяти он кидает bad_alloc, а если был указан пустой ( throw() ) — то возвращает null.


а еще операция new может быть переопределена. но за это по-моему руки отрывать нужно...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.