Re[22]: Блин, ну откуда столько криворуких?
От: kittown  
Дата: 12.07.06 08:26
Оценка:
Здравствуйте, Александр Каширин, Вы писали:

АК>Ээээ... ммм... тут скобки не помогут Что раньше выполняется — это определяется исключительно положением ++ относительнь указателя: прединкремент или постинкремент


Там есть оператор присваивания. Очень много всего в одном месте. В насмерть вылизанных либах еще еще может быть помещено из соображений эффективности, если она и впрямь достигается.

АК>Ну, например, в исходных кодах стандартных библиотек С (особенно работа со строками и с памятью) и С++ (в том же STL — добрая половина работы с итераторами включает постинкременты прямо в операции).


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

K>>Утверждение об эффективности тоже требует обоснования. Сможет ли оптимизатор привести ваш код к оптимальному машкоду ? Ему-то как раз сложные конструкции противопоказаны. Те, где активно применяются указатели, противопоказаны вдвойне...


АК>Ну что же сложного в конструкции из одного выражения и двух постинкрементов?


То, что работа с изменением указателей в памяти может оказаться медленнее, чем помещение адресов и индекса в регистры и использование относительной адресации. Зависит от низкоуровневой реализации проца. Но при любой реализации, отсутствие изменяемых указателей может позволить не держать их в кеше и ограничиться регистрами. Общий принцип processor-friendly кода — держаться подальше от указателей и их изменения. У C++ с этим проблемы, это да.

АК>А что Вы скажете о сложности такого кода:


АК>
АК>if(ptr && ptr->method())
АК>{
АК>    yes();
АК>    wow();
АК>}
АК>else
АК>{
АК>    no();
АК>    never();
АК>    out();
АК>}
АК>


АК>Тут есть примерно такое же мега-неудобство: нужно помнить, что стандартом языка С/С++ предусмотрено, что если в логическом выражении && первый операнд вернул 0, то второе даже не вычисляется (в данном случае — гарантия того, что обращения к памяти по адресу 0х00000000 не будет). Но ведь это же надо помнить! (!!!)


Это не просто стандартом C++ предусмотрено, это в большинстве известных мне языков предусмотрено. Данное поведение — одно из назначений операторов && и ||, а не второстепенный side effect.

АК>Неужели более читабельным и не менее эффективным, на Ваш взгляд, будет примерно так (тут уже помнить ничего не надо ):


АК>
АК>bool y = false;

АК>if(ptr)
АК>{
АК>    if(ptr->method()
АК>    {
АК>        yes();
АК>        wow();
АК>        y = true;
АК>    }
АК>}

АК>if(!y)
АК>{
АК>    no();
АК>    never();
АК>    out();
АК>}
АК>


Пример неподходящий, за исключением буленова y вместо else. Часто так и пишут, так что код нормальный. Но не для того, чтобы не писать &&, а по причине вызова нескольких методов вместо одного, или потому что логика лучше иллюстрируется (в том числе комментариями). И потому что во внешний if переодически что-то может добавляться. Вот если бы таких конструкций было бы много подряд, другое дело.
Re[22]: Блин, ну откуда столько криворуких?
От: kittown  
Дата: 12.07.06 08:33
Оценка:
Здравствуйте, Александр Каширин, Вы писали:

K>>Вопрос на засыпку — когда такой вариант окажется лучше ?


АК>О, кстати, интересно: я не могу придумать сколь-нибудь значимый пример того, когда бы этот вариант оказался лучше. Даже с учетом того, что процессор поддерживает индексную адресацию (т.е. вычислять адрес по два раза за цикл не нужно: нужно всего лишь прогрузить четыре регистра — и можно сразу обращаться к ячейке памяти) — все равно работа с инкрементом указателей оказывается эффективнее индексной адресации, как по скорости работы, так и по размеру объектного кода. Ну разве что в результате работы этого кода к концу цикла у нас остаются неизменными значения src и dst... но это ерунда.


АК>В общем, огласите, пожалуйста, весь список


Можно избежать расходы на содержание указателей в кеше и запись их измененных значений. Имеет ли это большое значение ? Неизвестно. но сам этот факт отметить и иметь в виду смысл есть.

Вообще же, самый правильный подход — писать код наиболее каноническим способом, чтобы это не значило, т.к. код пишется не для прямой трансляции в машкод, а для восприятия оптимизатором. Чем более знаком код оптимизатору, тем лучше результат.

Mikhail
Re[23]: Блин, ну откуда столько криворуких?
От: Александр Каширин  
Дата: 12.07.06 09:17
Оценка:
Здравствуйте, kittown, Вы писали:

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


АК>>Тут есть примерно такое же мега-неудобство: нужно помнить, что стандартом языка С/С++ предусмотрено, что если в логическом выражении && первый операнд вернул 0, то второе даже не вычисляется (в данном случае — гарантия того, что обращения к памяти по адресу 0х00000000 не будет). Но ведь это же надо помнить! (!!!)


K>Это не просто стандартом C++ предусмотрено, это в большинстве известных мне языков предусмотрено. Данное поведение — одно из назначений операторов && и ||, а не второстепенный side effect.


Как сейчас помню — в древние времена в Турбо-Паскале это регулировалось директивой компилятора и никаким стандартом не оговаривалось. А Delphi с его Паскалем в настоящее время отнюдь не вымерший язык... Так что полагаться на это просто так, по аналогии со знакомым языком нельзя: это надо точно знать.

Хотя я могу ошибаться: с тех пор, как я перестал активно использовать Паскаль, прошло уже 12 лет, и стандарты могли быть пересмотрены, чего я не уследил...

K>Пример неподходящий, за исключением буленова y вместо else.


В этом примере одним else не обойдешься: сделали из одного if два — извольте сделать и два else. Иначе функциональность кода будет другая. Поэтому и булевская переменная, а не две одинаковые ветки else.
Re[24]: Блин, ну откуда столько криворуких?
От: kittown  
Дата: 12.07.06 09:24
Оценка:
Здравствуйте, Александр Каширин, Вы писали:

АК>В этом примере одним else не обойдешься: сделали из одного if два — извольте сделать и два else. Иначе функциональность кода будет другая. Поэтому и булевская переменная, а не две одинаковые ветки else.


Это если после первого if фигурные скобки не ставить. За что и огрести моментально по рукам. Не зря их рекомендуется ставить всегда. Студентов по c++ гонял, так регулярно кто-то не ставил. И огребали по классическому сценарию — добавляли оператор и думали что он в теле. Сами огребали, без подсказки.
Re[21]: Блин, ну откуда столько криворуких?
От: Kestrel  
Дата: 12.07.06 09:28
Оценка:
Здравствуйте, Александр Каширин, Вы писали:


АК>Разница наблюдается в выбранных выше пунктах.


АК>"Есть ли реализация void dominanceTest() в IBase". В отличие от Java, в C++ реализация все-таки есть (хоть и абстрактная, но в соответствующей таблице виртуальных методов будет указатель на обработчик, который завалит программу с ошибкой "Pure virtual function called").

АК>В Java интерфейс — это исключительно декларативная вещь, которая не содержит никаких признаков реализации.

Вы уверены, что программа будет завалена с ошибкой "Pure virtual function called"
на всех платформах? Вас не затруднит указать место в стандарте C++, где сообщается
о том, что "реализация все-таки есть". Я, к сожалению, не нашёл. И как мне из
синтаксически корректной программы на C++ вызвать эту реализацию?
Re[22]: Блин, ну откуда столько криворуких?
От: Александр Каширин  
Дата: 12.07.06 09:44
Оценка:
Здравствуйте, Kestrel, Вы писали:

K>Вы уверены, что программа будет завалена с ошибкой "Pure virtual function called"

K>на всех платформах? Вас не затруднит указать место в стандарте C++, где сообщается
K>о том, что "реализация все-таки есть". Я, к сожалению, не нашёл. И как мне из
K>синтаксически корректной программы на C++ вызвать эту реализацию?

Например, так:

#include <iostream>
using namespace std;

class V
{
public:
    virtual void foo() = 0;

    virtual void bar()
    {
        foo();
    }

    V()
    {
        bar();
    }
};

class A : public V
{
public:
    virtual void foo()
    {
        cout << "This will not be called\n";
    }
};

int main(int argc, char* argv[])
{
    A a;

    return 0;
}


Компилируется и линкуется прекрасно, т.к. соответствует всем стандартам языка (хотя и не соответствует здравому смыслу — вызывать виртуальные функции из конструктора). В процессе выполнения Visual C++ 6.0 пример "упал" с ошибкой "runtime error". Ранее, когда я "баловался" с подобными примерами, я получал сообщение об ошибке "pure virtual function called". Очевидно, текст ошибки будет "платформенно-зависим"

О том, что "реализация все-таки есть", Вы сами упоминали, говоря о том, как наследуется "это поле" (речь шла о таблице виртуальных методов — там указатель на эту функцию таки да имеется... а чем он заполнен — по большому счету не важно).
Re[25]: Блин, ну откуда столько криворуких?
От: Александр Каширин  
Дата: 12.07.06 09:46
Оценка:
Здравствуйте, kittown, Вы писали:

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


АК>>В этом примере одним else не обойдешься: сделали из одного if два — извольте сделать и два else. Иначе функциональность кода будет другая. Поэтому и булевская переменная, а не две одинаковые ветки else.


K>Это если после первого if фигурные скобки не ставить. За что и огрести моментально по рукам. Не зря их рекомендуется ставить всегда. Студентов по c++ гонял, так регулярно кто-то не ставил. И огребали по классическому сценарию — добавляли оператор и думали что он в теле. Сами огребали, без подсказки.


Хм... в оригинале (где один if и &&) ветка else исполнялась в двух случаях:

— !ptr
— ptr && !ptr->method()

Вы же предлагаете обойтись одним else в случае двух if... как же так?
Re[23]: Блин, ну откуда столько криворуких?
От: algol Россия about:blank
Дата: 12.07.06 09:55
Оценка: +1
Здравствуйте, Дарней, Вы писали:

Д>такое вообще во многих компаниях практикуется, где требовательно относятся к качеству кода. хотя бьют обычно не по рукам, а скорее по кошельку


Так я все-таки не пойму, в чем заключается выпендреж. Если кто-то из разработчиков не понимает конструкции *src++, то это именно его нужно бить по голове резиновой дубинкой. Хотя это вряд ли поможет, если человек дурак, то это навсегда. Или возможно речь о формальных придирках, например большинство компиляторов выдадут warning, нужно писать типа "while((*dest++ = *src++) != 0);"?

A>>Кстати, а кто такой ArrayCopy? Это вообще из C? А то обычно идет сначала dst, а потом src.

Д>Это просто шаблонный метод. Неважно, откуда он взялся. Считай, что просто кто-то его написал

Отличный ответ на вопрос. Надо взять на заметку. Буду на любой код отвечать — за это нужно бить по кошельку резиновой дубинкой. Правильно будет — "Rabbit r = GetARabbitFromTheBlackBox(bb)". Неважно, откуда этот метод взялся, считай что просто кто-то его написал.
Я бы еще понял, если бы предложили использовать StrCpy(), lstrcpy(), strcpy()/_tcscpy() или еще что-нибудь аналогичное, но какой-то ArrayCopy(), который кто-то якобы написал — .
Re[26]: Блин, ну откуда столько криворуких?
От: kittown  
Дата: 12.07.06 09:56
Оценка:
Здравствуйте, Александр Каширин, Вы писали:

K>>Это если после первого if фигурные скобки не ставить. За что и огрести моментально по рукам. Не зря их рекомендуется ставить всегда. Студентов по c++ гонял, так регулярно кто-то не ставил. И огребали по классическому сценарию — добавляли оператор и думали что он в теле. Сами огребали, без подсказки.


АК>Хм... в оригинале (где один if и &&) ветка else исполнялась в двух случаях:


АК>- !ptr

АК>- ptr && !ptr->method()

АК>Вы же предлагаете обойтись одним else в случае двух if... как же так?


Формально вы правы. Просто я уже привык к коду, когда ветки else часто просто нет, а во вложенном if-е стоит break/return/continue, либо используются исключения.

Mikhail
Re[24]: Блин, ну откуда столько криворуких?
От: kittown  
Дата: 12.07.06 09:59
Оценка:
Здравствуйте, algol, Вы писали:

Д>>такое вообще во многих компаниях практикуется, где требовательно относятся к качеству кода. хотя бьют обычно не по рукам, а скорее по кошельку


A>Так я все-таки не пойму, в чем заключается выпендреж. Если кто-то из разработчиков не понимает конструкции *src++, то это именно его нужно бить по голове резиновой дубинкой.


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

Mikhail
Re[24]: Блин, ну откуда столько криворуких?
От: Дарней Россия  
Дата: 12.07.06 10:00
Оценка:
Здравствуйте, algol, Вы писали:

A>Так я все-таки не пойму, в чем заключается выпендреж. Если кто-то из разработчиков не понимает конструкции *src++, то это именно его нужно бить по голове резиновой дубинкой.


Объясняю, за что надо бить.
1. Это copy-paste распространенной реализации паттерна копирования
2. Этот код крайне небезопасен. Напоминаю — в точности такой же кусок кода обошелся MS в миллионы долларов убытков, не говоря уже о потере репутации.
... << RSDN@Home 1.1.4 stable rev. 510>>
Всех излечит, исцелит
добрый Ctrl+Alt+Delete
Re[25]: Блин, ну откуда столько криворуких?
От: Александр Каширин  
Дата: 12.07.06 10:11
Оценка:
Здравствуйте, Дарней, Вы писали:

Д>Здравствуйте, algol, Вы писали:


A>>Так я все-таки не пойму, в чем заключается выпендреж. Если кто-то из разработчиков не понимает конструкции *src++, то это именно его нужно бить по голове резиновой дубинкой.


Д>Объясняю, за что надо бить.

Д>1. Это copy-paste распространенной реализации паттерна копирования
Д>2. Этот код крайне небезопасен. Напоминаю — в точности такой же кусок кода обошелся MS в миллионы долларов убытков, не говоря уже о потере репутации.

Небезопасность кода ни у кого сомнения не вызывает, так что второй пункт оставим в покое. В конце концов, заменим код на такой:

for(dest[--maxsize] = '\0'; maxsize-- && *dest++ = *src++; )
; // do nothing

Этот код безопасен — давайте рассматривать его.

По первому пункту — формулировка "copy-paste" в данном контексте вообще непонятна.
Re[25]: Блин, ну откуда столько криворуких?
От: algol Россия about:blank
Дата: 12.07.06 10:16
Оценка: +2
Здравствуйте, kittown, Вы писали:

K>Дело не просто в "понимает-не понимает", а в том, с какой легкостью и скоростью понимает. Продираться через подобный код тоже можно, но это дольше и ошибки более вероятны.


Тогда я не пойму вообще, о чем разговор. Сначала на собеседовании вы рассуждаете о паттернах и виртуальном наследовании, а потом выясняется, что большинство разработчиков — выпускники вспомогательной школы, которые не в состоянии понять конструкцию *src++? То есть на собеседовании вы просто гнете пальцы, а потом берете всех подряд, потому что людей не хватает?
Re[25]: Блин, ну откуда столько криворуких?
От: algol Россия about:blank
Дата: 12.07.06 10:21
Оценка:
Здравствуйте, Дарней, Вы писали:

Д>Объясняю, за что надо бить.

Д>1. Это copy-paste распространенной реализации паттерна копирования

"Ты не умничай, ты пальцем покажи" (с) анекдот про чукчу и подводную лодку. Так можно увидеть правильную реализацию? Хочется понять, как нужно правильно делать, чтобы не получить дубиновой резинкой по кошельку.

Д>2. Этот код крайне небезопасен. Напоминаю — в точности такой же кусок кода обошелся MS в миллионы долларов убытков, не говоря уже о потере репутации.


Т.е. вопрос просто в проверке на размер буфера? Такой код будет кошерным или это тоже выпендреж?
    int cnt = bufSize;
    while(cnt-- && (*dest++ = *src++));"
Re[26]: Блин, ну откуда столько криворуких?
От: kittown  
Дата: 12.07.06 10:23
Оценка:
Здравствуйте, algol, Вы писали:

A>Здравствуйте, kittown, Вы писали:


K>>Дело не просто в "понимает-не понимает", а в том, с какой легкостью и скоростью понимает. Продираться через подобный код тоже можно, но это дольше и ошибки более вероятны.


A>Тогда я не пойму вообще, о чем разговор. Сначала на собеседовании вы рассуждаете о паттернах и виртуальном наследовании, а потом выясняется, что большинство разработчиков — выпускники вспомогательной школы, которые не в состоянии понять конструкцию *src++? То есть на собеседовании вы просто гнете пальцы, а потом берете всех подряд, потому что людей не хватает?


Опять 25. Вы прочитали на что отвечаете ? Дело отнють не в способности ее понять. То, что эта конструкция понимается хуже других, не зависит от степени профессионализма сотрудников. Более опытные работают с ней легче, менее опытные — хуже, но все они работают с ней хуже, чем с более простым кодом. У меня, когда я работаю с кодом, всегда найдется лучшее применение мозгам, чем вдаваться в детали каждой такой конструкции.

Mikhail
Re[26]: Блин, ну откуда столько криворуких?
От: jhfrek Россия  
Дата: 12.07.06 10:34
Оценка:
Здравствуйте, Александр Каширин, Вы писали:

АК>for(dest[--maxsize] = '\0'; maxsize-- && *dest++ = *src++; )

АК> ; // do nothing
АК>По первому пункту — формулировка "copy-paste" в данном контексте вообще непонятна.

Все очень просто — какие типы у dest и src и что будет, если эти типы произвольно менять?
Re[20]: Блин, ну откуда столько криворуких?
От: Eurispheus Россия  
Дата: 12.07.06 10:36
Оценка:
Здравствуйте, WindWalker, Вы писали:

E>>Эта тема уже обсуждалась. Действительно, при уровне дохода, при котором +/- $500 еще имеет значение, з/п при выборе места работы стоит на первом месте.

WW>Поясняю минус. +-500$ становятся безразличными, когда эти самые +- <10% от зарплаты. Т.е. при зарплате 10000$ / месяц да, пофиг. А хотя бы 5000 — что-то да значит.

Таки не понял, за что минус
Я сказал ровно тоже самое.

PS 10% от $10000 — это $1000. Для $5000 — это $500.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[23]: Блин, ну откуда столько криворуких?
От: Kestrel  
Дата: 12.07.06 10:37
Оценка:
Здравствуйте, Александр Каширин, Вы писали:

АК>Компилируется и линкуется прекрасно, т.к. соответствует всем стандартам языка (хотя и не соответствует здравому смыслу — вызывать виртуальные функции из конструктора). В процессе выполнения Visual C++ 6.0 пример "упал" с ошибкой "runtime error". Ранее, когда я "баловался" с подобными примерами, я получал сообщение об ошибке "pure virtual function called". Очевидно, текст ошибки будет "платформенно-зависим"


АК>О том, что "реализация все-таки есть", Вы сами упоминали, говоря о том, как наследуется "это поле" (речь шла о таблице виртуальных методов — там указатель на эту функцию таки да имеется... а чем он заполнен — по большому счету не важно).


Вы меня убедили, предлагаю закончить.
Re[27]: Блин, ну откуда столько криворуких?
От: algol Россия about:blank
Дата: 12.07.06 10:43
Оценка: 1 (1) +1
Здравствуйте, kittown, Вы писали:

K>Опять 25. Вы прочитали на что отвечаете ? Дело отнють не в способности ее понять. То, что эта конструкция понимается хуже других, не зависит от степени профессионализма сотрудников. Более опытные работают с ней легче, менее опытные — хуже, но все они работают с ней хуже, чем с более простым кодом. У меня, когда я работаю с кодом, всегда найдется лучшее применение мозгам, чем вдаваться в детали каждой такой конструкции.


Странно, я всегда считал, что конструкция "while(*dest++ = *src++);" распознается нормальным разработчиком на уровне зрительных образов, без включения мозгов. Например когда смотрю на карандаш, то понимаю что это карандаш, не пытаясь при этом проанализовать форму предмета, прочитать что на нем написано, пощупать из чего этот предмет сделан и т.д.
Re[18]: Блин, ну откуда столько криворуких?
От: alcotras  
Дата: 12.07.06 10:50
Оценка:
Здравствуйте, Геннадий Васильев, Вы писали:

ГВ>А на поддержку, значит, традиционно приглашаем новичков. Следовательно, любой код должен быть ориентирован на новичков. Так?


Именно! Задачи кода — 1. реализовывать бизнес-функции максимально полно 2. быть как можно проще в поддержке. Так что использование выкрутасов типа виртуального наследования в реальном проекте ИМХО что художника из Строгановки приглашать покрасить забор.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.