Нашли или выдавили из себя код, который нельзя назвать нормальным,
на который без улыбки не взглянешь?
Не торопитесь его удалять или рефакторить, — запостите его на
говнокод.ру, посмеёмся вместе!
А в COM такая форма передачи выходных параметров используется для совместимости с Си, так что это правильно. Хотя не вижу никакого удовольствия писать под COM на си.
Если уж писать на крестах - то лучше сделать нормальный смартпоинтер. А от ссылки никакого толку нет - код перестанет быть совместимым с си, а удобства не прибавится.
explicit добавь в GovnoPtr(T * p)
поддержки const корректности не хватает
T * operator = (T *p) { не безопасен с точки зрения исключений и не хваает такого же оператора, только копирования
DLL поидеи тоже не может кидать исключения, но на деле что для DLL, что COM разрешают кидать исключения, когда пишут в рамках этих технологий, но на одном компиляторе и настройках в одном проекте. Не спрашивай зачем, возможно для модульности. Вообщем лучше от таких питушков уберечься, так как это почти ничего не стоит.
> DLL поидеи тоже не может кидать исключения
Моя DLL, че хочу то и делаю. Соглашения о вызовах и исключениях не зафиксированы, поэтому я всегда могу написать свои и следовать им.
А вот COM это не та вещь, в которой допустимы вольности. Не нравятся правила COM'а - мути свою аналогичную технологию, но не создавай людям батхерты, называя это COM'ом.
К тому же "Exceptions aren't allowed to flow across a COM interface boundary. Because there is no binary contract for C++ exceptions, COM cannot marshal them from one thread to another.". Т.е. с COM объектом из соседнего процесса так уже не поработаешь.
P.S. Исключение в Release равносильно исключению в деструкторе.
COM же. Методы интерфейса IUnknown, от которого порождены все остальные интерфейсы.
AddRef увеличивает счетчик использований на 1. Release уменьшает, и удаляет объект, если счетчик достиг нуля. QueryInterface позволяет получить другой интерфейс по его GUID'у.
Он не нашел, он привел пример, на котором этот макрос поведет себя неадекватно - else уйдет внутрь макроса, а не к тому ифу, к которому должно относиться.
Основы макроёбства - не жалеть скобок в выражениях и do { ... } while (0) в стейтментах, чтобы потом об этом не жалеть 😉
Макрос завернутый в do { ... } while (0) ведет себя неотличимо от функции в том плане, что требует ставить после него ";". А с голым блоком { ... } получается наоборот, что не всегда приятно.
Сравни
if (a)
SAFE_FREE(x)
else
SAFE_FREE(y)
и
if (a)
SAFE_FREE(x);
else
SAFE_FREE(y);
Второе, естественно, смотрится привычней и интуитивней.
> Лучше так
Нет, не лучше. Этот вариант забагуется на примере Романа, равно как и просто { ... }. Конструкцию с if(0){}else{...} юзают не в таком случае, а когда макросом пытаются эмулировать какой-нибудь foreach или особый if.
Емнип других способов замутить макрос, ведущий себя как вызов void функции кроме do { ... } while(0) и нет.
> макросом пытаются эмулировать какой-нибудь foreach или особый if.
Пример использования if(0){}else для foreach и\или if ? if(0){}else - если это не работает, то зачем так делают?
> если это не работает, то зачем так делают
Оно работает, но семантика получается как у любой другой управляющей конструкции - if/for/while и т.п. Вот для эмуляции новых подобных конструкций оно юзабельно. Для эмуляции void функций - нет.
> Пример использования if(0){}else для foreach
В Qt'шной реализации foreach'а for завернут в if(0){}else чтобы переменные, описанные в for'е не вылезали наружу из-за ебанутого скопинга в msvc6. Если интересно, а искать исходники кютихи влом - могу выложить сюда этот кусочек.
Естественнее смотрится Паскаль, в котором перед else точка с запятой никогда не ставится, потому что точка с запятой будет означать конец всего оператора if.
А вообще же тот, кто уже обжёгся, ставит фигурные скобки при каждом удобном случае, даже вокруг единственного оператора:
> Я всегда ставлю скобки.
А я ставлю их в нетривиальных случаях - более одного уровня вложенности. Примерно так:
// здесь без скобок
if (x)
x->release();
// если одна из веток сложна - скобки пишу в обе стороны
if (x) {
x->show();
} else {
y->show();
z->show();
}
// два и более уровней вложенности - тоже скобки
for (int i=0; i<10; i++) {
for (int j=0; j<10; j++) {
printf("%d %d\n", i, j);
printf("%d %d\n", i, j);
}
}
// но
for (int i=0; i<10; i++)
for (int j=0; j<10; j++)
a[i][j] = 5;
> Разве так не надёжнее?
Скобки то само-собой надежнее. Но согласитесь: лучше написать макрос (а лучше вообще не писать их лишний раз без причины 😉 так, чтобы он адекватно работал во всех контекстах, чем объяснять в документации как именно нужно его юзать, и надеяться, что ее будут читать...
> А вообще же тот, кто уже обжёгся, ставит фигурные скобки при каждом удобном случае
Обжегшись на молоке дуют на воду... Проблема то в том, что макрос через жопу написан. А пофиксить пытаются последствия.
Из всех макросов полезен только SAFE_RELEASE. От остальных польза разве что в запихивании NULL'а. Но в любом случае для с++ они как-то не особо идиоматичны.
P.S. Кстати макросы написаны неправильно, нужно больше do { ... } while(0).
Коллеги, работавшие в мотороле, рассказывают слезливые истории про их нестандартные функции освобождения памяти, вызывающие ребут телефона при передаче им NULL. Десткая психика не выдержала травмы, никак не могу отучить их писать эти проверки.
> вызывающие ребут телефона при передаче им NULL
Ужоснах какой-то. В чем смысл такой функции? Оптимизация путем устранения лишней проверки? Так один хер все в страхе будут проверять, и проверка вернется, правда вместо одного места она будет размазана по всему коду ровным слоем...
http://msdn.microsoft.com/en-us/library/windows/desktop/dd940435(v=vs.85).aspx
Лучше. Она хотя бы не так забагована, как макросы, перечисленные выше 😉
да, также как и в T * operator = (T *p) {
поддержки const корректности не хватает
T * operator = (T *p) { не безопасен с точки зрения исключений и не хваает такого же оператора, только копирования
> поддержки const корректности
Логично
> не безопасен с точки зрения исключений
Зачем AddRef и Release будут кидать исключения? Они ведь даже не крестоблядские...
Моя DLL, че хочу то и делаю. Соглашения о вызовах и исключениях не зафиксированы, поэтому я всегда могу написать свои и следовать им.
А вот COM это не та вещь, в которой допустимы вольности. Не нравятся правила COM'а - мути свою аналогичную технологию, но не создавай людям батхерты, называя это COM'ом.
К тому же "Exceptions aren't allowed to flow across a COM interface boundary. Because there is no binary contract for C++ exceptions, COM cannot marshal them from one thread to another.". Т.е. с COM объектом из соседнего процесса так уже не поработаешь.
P.S. Исключение в Release равносильно исключению в деструкторе.
AddRef увеличивает счетчик использований на 1.
Release уменьшает, и удаляет объект, если счетчик достиг нуля.
QueryInterface позволяет получить другой интерфейс по его GUID'у.
http://msdn.microsoft.com/en-us/library/windows/desktop/bb761722(v=vs.85).aspx
fxd
Основы макроёбства - не жалеть скобок в выражениях и do { ... } while (0) в стейтментах, чтобы потом об этом не жалеть 😉
СравнииВторое, естественно, смотрится привычней и интуитивней.
Лучше так:
Нет, не лучше. Этот вариант забагуется на примере Романа, равно как и просто { ... }. Конструкцию с if(0){}else{...} юзают не в таком случае, а когда макросом пытаются эмулировать какой-нибудь foreach или особый if.
Емнип других способов замутить макрос, ведущий себя как вызов void функции кроме do { ... } while(0) и нет.
Пример использования if(0){}else для foreach и\или if ? if(0){}else - если это не работает, то зачем так делают?
Оно работает, но семантика получается как у любой другой управляющей конструкции - if/for/while и т.п. Вот для эмуляции новых подобных конструкций оно юзабельно. Для эмуляции void функций - нет.
> Пример использования if(0){}else для foreach
В Qt'шной реализации foreach'а for завернут в if(0){}else чтобы переменные, описанные в for'е не вылезали наружу из-за ебанутого скопинга в msvc6. Если интересно, а искать исходники кютихи влом - могу выложить сюда этот кусочек.
Не, спасибо. Я видел. Тот щё гонокод. Хуже только BOOST_FOREACH
А вообще же тот, кто уже обжёгся, ставит фигурные скобки при каждом удобном случае, даже вокруг единственного оператора: Разве так не надёжнее?
А я ставлю их в нетривиальных случаях - более одного уровня вложенности. Примерно так:
А я потом понять не мог, почему у меня память течь начала, да и ещё в промышленных масштабах, по 3 мб на одну отрисовку
Скобки то само-собой надежнее. Но согласитесь: лучше написать макрос (а лучше вообще не писать их лишний раз без причины 😉 так, чтобы он адекватно работал во всех контекстах, чем объяснять в документации как именно нужно его юзать, и надеяться, что ее будут читать...
> А вообще же тот, кто уже обжёгся, ставит фигурные скобки при каждом удобном случае
Обжегшись на молоке дуют на воду... Проблема то в том, что макрос через жопу написан. А пофиксить пытаются последствия.
P.S. Кстати макросы написаны неправильно, нужно больше do { ... } while(0).
Ужоснах какой-то. В чем смысл такой функции? Оптимизация путем устранения лишней проверки? Так один хер все в страхе будут проверять, и проверка вернется, правда вместо одного места она будет размазана по всему коду ровным слоем...
Это фича!