Бросание глобального объекта в исключении
От: ShubinEV Россия http://erladvisor.blogspot.de/
Дата: 13.11.10 08:44
Оценка:
Есть класс A.
class A;

В одном из модулей создается глобальный объект этого класса.
A g_a;

Можно ли бросить исключение следующим образом:
throw g_a;

Такой код компилируется и даже работает, но:
1. На подсознательном уровне чувствую, что так делать неправильно.
2. Ниразу не видел такого ни в одной книге или в открытом коде.

Развейте, пожалуйста, мои сомнения, или помогите их аргументировать.
Меняется ли ситуация если глобальный объект константный.
const A g_a;
Re: Бросание глобального объекта в исключении
От: Erop Россия  
Дата: 13.11.10 09:20
Оценка:
Здравствуйте, ShubinEV, Вы писали:

SEV>Развейте, пожалуйста, мои сомнения, или помогите их аргументировать.

SEV>Меняется ли ситуация если глобальный объект константный.
Так делать можно, если у класса есть доступный конструктор копии.
Но, возможно, это сделает не то, что ты хочешь. Полетит всё равно копия глобального объекта, а не он сам.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Бросание глобального объекта в исключении
От: Chorkov Россия  
Дата: 13.11.10 09:21
Оценка:
Здравствуйте, ShubinEV, Вы писали:

...
SEV>Такой код компилируется и даже работает, но:
SEV>1. На подсознательном уровне чувствую, что так делать неправильно.
SEV>2. Ниразу не видел такого ни в одной книге или в открытом коде.

SEV>Развейте, пожалуйста, мои сомнения, или помогите их аргументировать.


Будет брошена копия глобального объекта, а не ссылка на него, как ты, вероятно, думал.

15.1.3
A throw-expression initializes a temporary object, called the exception object, the type of which is determined by removing
any top-level cv-qualifiers from the static type of the operand of throw and adjusting the type from “array of T”
or “function returning T” to “pointer to T” or “pointer to function returning T”, respectively. [ Note: the temporary object
created for a throw-expression that is a string literal is never of type char* or wchar_t*; that is, the special conversions
for string literals from the types “array of const char” and “array of const wchar_t” to the types “pointer to char”
and “pointer to wchar_t”, respectively (4.2), are never applied to a throw-expression. —end note ] The temporary is
an lvalue and is used to initialize the variable named in the matching handler (15.3). The type of the throw-expression
shall not be an incomplete type, or a pointer to an incomplete type other than (possibly cv-qualified) void. Except for
these restrictions and the restrictions on type matching mentioned in 15.3, the operand of throw is treated exactly as a
function argument in a call (5.2.2) or the operand of a return statement.



Бросание копии объекта не дает никаких приимуществ перед прямым созданием экземпляра объекта.
  throw exception_type("message");

Если есть исключение, которое часто бросается из разных точек программу (с одним и темже сообщением),
то есть смысл специализировать класс исключения:
  throw special_exception_type();


SEV>Меняется ли ситуация если глобальный объект константный.

SEV>
SEV>const A g_a;
SEV>


Нет. Не меняется.
  Скрытый текст
#include <iostream>

class A
{
public:
    A()         { std::cerr<< "c-tor " << this <<std::endl; }
    A(const A&) { std::cerr<< "copy c-tor " << this <<std::endl; }
    ~A()        { std::cerr<< "d-tor " << this <<std::endl; }
};

const A a;

int main(int argc, char *argv[])
{
    try
    {
        throw a;
    }
    catch(A& err)
    {
        std::cerr<<" At catch:\n"
                << "&a  = " << &a <<"\n"
                << "&err= " << &err << "\n";
    }

    return 0;
}


c-tor 00409158
copy c-tor 002DFF53
 At catch:
&a  = 00409158
&err= 002DFF53
d-tor 002DFF53
d-tor 00409158
Re: Бросание глобального объекта в исключении
От: Bell Россия  
Дата: 13.11.10 09:31
Оценка:
Здравствуйте, ShubinEV, Вы писали:

При выбрасывании исключения создается копия объекта — исключения. В ряде случаев компилятор может произвести оптимизацию, и обойтись без создания временного объекта. Использование глобального объекта в качестве аргумента throw в обоих этих случаях вполне позволительно
Любите книгу — источник знаний (с) М.Горький
Re: Бросание глобального объекта в исключении
От: Stanislav V. Zudin Россия  
Дата: 13.11.10 11:03
Оценка:
Здравствуйте, ShubinEV, Вы писали:

SEV>Можно ли бросить исключение следующим образом:

SEV>
SEV>throw g_a;
SEV>

SEV>Такой код компилируется и даже работает, но:
SEV>1. На подсознательном уровне чувствую, что так делать неправильно.

Про бросание копии уже написали. Но ты можешь кидать указатель, как это делается в MFC.
throw &g_a;
_____________________
С уважением,
Stanislav V. Zudin
Re[2]: Бросание глобального объекта в исключении
От: MasterZiv СССР  
Дата: 13.11.10 12:13
Оценка: -2
On 13.11.2010 14:03, Stanislav V. Zudin wrote:

> Про бросание копии уже написали. Но ты можешь кидать указатель, как это делается

> в MFC.

Ведущие плюсологи мира уже давно доказали, что это -- плохой стиль.
Posted via RSDN NNTP Server 2.1 beta
Re[3]: Бросание глобального объекта в исключении
От: uzhas Ниоткуда  
Дата: 13.11.10 12:31
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>Ведущие плюсологи мира уже давно доказали, что это -- плохой стиль.

С глобальными объектами они тоже уже определились
Re[3]: Бросание глобального объекта в исключении
От: dead_ricky  
Дата: 14.11.10 11:19
Оценка:
>> Про бросание копии уже написали. Но ты можешь кидать указатель, как это делается
>> в MFC.

MZ>Ведущие плюсологи мира уже давно доказали, что это -- плохой стиль.


Расскажите почему.
Re[4]: Бросание глобального объекта в исключении
От: Stanislav V. Zudin Россия  
Дата: 14.11.10 14:20
Оценка: 2 (1)
Здравствуйте, dead_ricky, Вы писали:

>>> Про бросание копии уже написали. Но ты можешь кидать указатель, как это делается

>>> в MFC.

MZ>>Ведущие плюсологи мира уже давно доказали, что это -- плохой стиль.


_>Расскажите почему.


Ведущие плюсологи также осуждают goto, что не означает, что этой командой нельзя пользоваться.

В бросании по указателю есть нюанс — неизвестно, кто отвечает за время жизни объекта исключения. Если объект был создан по new, то его надо после поимки удалить. Если кидался указатель на глобальный объект, то удалять не надо. Если ты специально не обработал исключение и оно угодило в catch(...), то в первом случае происходит утечка памяти.

В MFC в интерфейсе CException есть метод Delete (точно название не помню), который надо вызвать в обработчике исключения. Кроме этого, при конструировании объекта надо выставить флажок, который определяет, надо ли убивать объект при вызове Delete или нет (для глобального объекта ессно не надо).

Т.е. если следовать правилам и программировать аккуратно, то ничего криминального не случится.
_____________________
С уважением,
Stanislav V. Zudin
Re: Бросание глобального объекта в исключении
От: jazzer Россия Skype: enerjazzer
Дата: 15.11.10 01:00
Оценка:
Здравствуйте, ShubinEV, Вы писали:

Можешь попробовать кинуть boost::ref/cref(g_a) — копирования не будет, семантика прозрачна.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.