- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
calculateSomething(int n){
float* x = new float[n];
/*do smth*/
if ( /*validation*/ ) {
delete[] x;
return;
}
float* y = new float[n];
/*do smth*/
if ( /*validation*/ ) {
delete[] x;
delete[] y;
return;
}
float* z = new float[n];
/*next step*/
if ( /*smth goes wrong*/ ) {
delete[] x;
delete[] y;
delete[] z;
return;
}
/*more calculations with validation*/
delete[] x;
delete[] y;
...
/*more delete[]*/
return;
}
Принципиальная схема говногода, найденного на просторах сети.
Здесь нужно соблюдать порядок между этими EXIT_ и порядком создания, ошибкоопасно.
Если есть возможность безопасно вызвать free на нулевой, скажем, указатель, то лучше все инициализировать вначале нулями, а в самом конце все освободить, и туда, в конец, бросать из всех неудачных валидаторов. Хотя код всё же придётся менять в двух местах, но уже не по всей функции.
Конечно есть.
Вы правы - лучше сделать одну метку, после которой стоит пачка free.
Программирование на С вообще достаточно опасное занятие.
Но мы ведь не боимся трудностей, правда?
>Если есть возможность безопасно вызвать free на нулевой, скажем, указатель
то лучше все инициализировать вначале нулями
$ man 3 malloc
…
The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behavior occurs. If ptr is NULL, no operation is performed.
…
The malloc() and calloc() functions return a pointer to the allocated memory that is suitably aligned for any kind of variable. On error, these functions return NULL. NULL may also be returned by a successful call to malloc() with a size of zero, or by a successful call to calloc() with nmemb or size equal to zero.
…
Если вы обратили внимание переход по меткам осуществляется в порядке обратном выделению памяти. т. е. если происходит переход на EXIT_Y, то это значит, что код
по Х -ветке отработал успешно(понятно что в в этом упрощённом примере, не принимается во внимание действия м/у выделением памяти и некой валидацией, хотя что там ещё может быть, как не проверка валидности выделенной памяти — не знаю).
А мало ли что ещё может взбрести в голову программистам, которые и в простом случае, да ещё и на C++ умудряются такое выдать.
Вот в таком виде это действительно будет работать. При этом не обязательно использовать malloc free, а можно и new[]/delete[].
> При этом не обязательно использовать malloc free
Я предполагал, что это С. А на с++ ни к чему эти извраты.
Их NULL'ами инициализирует malloc() , в случаи фейла.
Не инициализирует, если выполнение туда не дойдет.
В случае с одной меткой, освобождение будут проходить все ресурсы
вне зависимости от того были ли они использованы при попытке выделения памяти или нет.
В случае с множественными метками, освобождение будут проходить только те
ресурсы, которые на момент не прохождения валидации одним из ресурсов
были инициализированы, а также сам ресурс(на ктором malloc() обфейлился, но инициализировал его NULL'ом).
для наглядности можно параллельно иметь enum с говорящими именами
в случае ошибки из всех мест делается единый goto cleanup
а там уже делается switch (runlevel) с кейсами последовательно от максимального значения до 1 без брейков
А ваш способ с runlevel он, скорее, для ресурсов типа файлов и сокетов.
Еще вариант для С, которым я пользовался - заполняем переменные NULLами (или -1 если у нас файлы или сокеты), при ошибке прыгаем на cleanup, где для всех не NULL'овых (не -1) переменных вызываем соответствующую функцию освобождения ресурса.
Плюс - хорошая развязка между кодом, который получает ресурсы, и кодом, который их освобождает (не надо поддерживать runlevel или писать дополнительные метки, не имеет значения порядок получения ресурсов).
Минус - немного медленнее, порядок освобождения может не совпасть с порядком получения.
странно, Тарас, не правда ли?
повзрослей уже
за логами сколько у меня аккаунтов на гк - к страйкеру
боюсь, ответ тебя удивит
Ребята, зачем усложнять себе жизнь?
Тарас, ходят слухи, что у тебя баттхёрты по поводу минурастов. Искренне, скорейшего выздоровления тебе.
P.S. В говнокоде++ хочу возможность переголосовать в течение некоторого времени. И разнести чёртовы кнопочки.
Это воистину худший вариант. Даже просто голый текст - и то лучше...
Ещё можно хвалиться, у кого код наиболее говняный. Особые мастера могут написать ридер на баше.
[offtop]Bormand, начинает казаться, что вы смайлофажите.[/offtop]
Ага, на закуску к пиву.
[offtop]Кто смайлофаг ;) Я ;) Как вы это определили? )))[/offtop]
По сути - тоже самое, но в профиль.
Про ресурсоёмкость не пишу, ибо компиляторы нынче шибко умные пошли.
goto хейтеры довольны
wtf двойной брейк?
start
inner loop
still in one-pass loop
outside
в любом случае, всё прекрасно будет работать без goto, если включить голову
Выход из двойного цикла иногда нужен именно по алгоритму.
Флагоебство не нужно, т.к. снижает и наглядность и производительность сильнее чем goto.
А выход из двойного цикла - проблема и в С++.
Скинь, пожалуйста, пример кода, в котором требуется даблбряк (полностью функцию), попробуем что-нибудь сделать с ним.
Убей их. Они слишком много знают.
А если серьезно - если кроме методов класса никто не видит - это уже хорошо.
Код в студию ;)
Локальная функция:
- локальна на функцию.
А также анонимный немспейс:
- локальна на модуль cpp
http://ideone.com/TzUwa
с++03 compartible:
Ты чего с аватарки фак показываешь или у виска крутишь?
анализирую
Ада?
расслабься и жди поддержки стандарта
Расслабьтесь и попытайтесь получить удовольствие...
2)Настоящие сервера, крутящиеся годами (те что пишутся на си) - пишутся так, что каждый запрос обслуживается в отдельном процессе. Так что в atexit для освобождения части ресурсов самое время.
Не все. Иногда запросы мелкие и их много.
Но тогда, они и годами не крутятся или очень простые или опять же пишутся годами.
При множественном break; последующие просто не достигаются.
На первом же выскакивает из цикла, а остальные не у дел, как код после return;
И continue тоже не достигается. Как встретился, так цикл продолжился, а следующий не успевает исполниться.
Т.е. нужен какой-то дополнительный оператор. break в метку или break(<количество вложений>); как-то так.
Вопрос был риторическим, как очередное доказательство неправильности суждений @TarasB о брэйках.
Карма, она не на сервере, она в голове.
Хотя бывает и специально: http://www.gamedev.ru/code/forum/?id=139163
Знатный срачелло там, кстати.
Разве что там какие-то ограничения на размещение в стеке, но тогда сразу должна была прийти мысль, о захвате ресурса другим, уже автоматическим объектом (да RAII).
А тут мы видим, что люди шарашат динамическую память без понятия и компилятор не может им помочь избавиться от лишней работы по написанию delete[]. А если таких вычислительных функций не одна, а десять? Это же какой потенциал для ошибки!
Такой код нужно студентам на лекции показывать :)
VLA? Они, конечно, удобны, но при невнимательности можно словить stack overflow.
На выбор остаются векторы и scoped_ptr.
> Такой код нужно студентам на лекции показывать :)
Не стоит, выучат же.
Какой "автоматические массивы"? Поясните мысль.
int arr[N] на стеке, как было в С, так в С++ этого точно нет. Если только какое то расширение компилятора.
Ну и в случае POD-типов, как здесь, можно использовать alloca.
В MS VS это _alloca и более правильная _malloca
Сомневаюсь, что это часть стандарта (могу ошибаться), но вроде как поддерживается многими компилями.
int arr[n];
Для C++ это избыточно, но, тем не менее... Это, по крайней мере, уже указывает на то, что программист понимает, что семантика памяти должна быть автоматической. Хотя, всё равно, явные пробелы в познаниях std::
Ниже уже рассказали, что C++ так не умеет.
Александр Македонский тоже великий полководец, но зачем же стулья ломать?
Зато C умеет, сказали ниже, значит можно отмести версию, что код выше -- это нормально для C.
P.S. Вы не в ту сторону смотрите.
И чем VLA помогут сделать этот код лучше? У вас есть гарантия, что n достаточно мало и мы не получим stack overflow?
VLA для массивов неконтролируемой длины это зло.
То есть вы мужчина
>http://www.govnokod.ru/10569#comment143901
Как бы это помягче спросить...
Чтобы уж вам не спрашивать.
В виду последних эпичных тредов начал подумывать, не изучить ли c++ по человечески чтобы всех троллить. Но теперь вкрадываются сомнения, стоит ли....
Программистов на С++ гораздо больше. Так что не бойтесь. Изучайте.
Вопрос в том... А нуно ли вам это? Занимаетесь ли вы такими вещами, что вам C++ нужен...
Несмотря на то, что метапрограммированию в с++ достаточно далеко от того, что можно делать в lisp, подходы всё равно интересны. Да и просто неприятно открывать продвинутый цппшный код и не понимать, что за неведомая х**ня там творится.
Конечно, гораздо больше интереса у меня вызывает функциональное программирование и большие распределённые высоконагруженные системы. Но мой жизненный опыт гласит, что для того, чтобы летать в облаках функциональщины, нужно уметь твёрдо стоять на грешной c/c++ земле. И если с C у меня особых проблем нет, то вот c++ код бывает непонятным довольно часто.
ромбовидное_наследование.cxx
В C++ вообще массивы C-style -- это нехорошо. Есть мощная и удобная стандартная библиотека.
В C наличие таких массивов было бы действительно удобным, а в С++ уже избыточно. При такой-то необъятной стандартной библиотеке!
>Не стоит, выучат же.
Прально! Выучат, что это плохо. Будут пользовать std::
float* x = new float[n];
...
if (! /*validation*/ ) {
float* y = new float[n];
...
if (! /*validation*/ ) {
...
}
delete[] y;
}
delete[] x;
зы. подразумевается работа без генерации исключений
Для c++ именно этим и плох.
Кстати, со scoped_ptr код короче, надежнее, понятнее и эквивалентен по производительности.
Вопрос не только в копипасте большого количества delete[], хотя, предложенный вариант, вне всяких сомнений легче отследить, но и в том, что "ручное" освобождение памяти не нужно. Память имеет автоматическую семантику: точно известно где и когда создать и точно известно, где и когда убрать. Пример, конечно, уж совсем тривиальный, потому что здесь даже не нужно выделять структурных блоков видимости, чтобы делегировать управление вставку вызовов работы с памятью компилятору.
Нужно. В тех случаях когда скопы, деревья наследования и счетчики ссылок уже не спасают. Ну и, конечно, для реализации всех этих способов освобождения памяти.
Я говорю, про "не нужно" в конкретном примере.
Очень часто люди используют семантику динамической памяти, когда видно, что семантика автоматическая или статическая. Да, технически, приходится прибегать к куче и использовать аллокацию и освобождение памяти, но это можно спрятать, ведь есть возможности ООП по сокрытию технической реализации.
Полагаю, такого не может произойти, что в коде образуется кусок памяти, который невозможно освободить. Существование сборщиков мусора говорит о том, что это возможно. Есть какой-нибудь 1% кода, когда это действительно затруднительно.
Но может быть это просто наша ошибка? Может стоит пересмотреть пост-пред условия контрактов, как-то поменять весь алгоритм, чтобы стало проще? Может мы изначально выбрали неверное архитектурное исполнение?
Здесь масса причин может быть.
По крайней мере, существование сборщиков мусора в управляемых языках показывает, что уборка этого 1% может быть сделана. Причём, зная конкретно структуру свой программы, скорее всего, можно организовать это ещё более эффективно. И всего-то в одном случае из ста. Да и то, это я хватанул. Такие ситуации исчисляются сотыми долями процента и весьма специфичны, для них, наверняка, есть велосипеды.
std::unique_ptr
boost::scoped_array
#if defined (WIN32) ...
тебе разве не достаточно
http://msdn.microsoft.com/en-us/library/wb1s57t5.aspx
http://www.kernel.org/doc/man-pages/online/pages/man3/alloca.3.html
http://www.opennet.ru/man.shtml?topic=alloca&category=3&russia n=1 // freebsd
Но они никому не нужны, т.к. можно без проблем создать класс, пользующийся alloca на мелких N и кучей на больших N. В этом случае имеем профит сопоставимый с VLA на мелких массивах, и не боимся вызвать stack overflow.
P.S. А есть в бусте такой класс?
был в с++11 proposal о dynarray<T>, но вроде как его отклонили
зы. в с++ VLA?
Может в буст добавили.
внимательный зритель, кстати, заметит, что аллокация в этом dynarray делается по миссионерски - new char[ n*sizeof(T) ];
фактически, несложно написать свой враппер над alloca, вызывая деструкторы объектов в массиве по выходу из scope, только стек всё равно освободится при выходе из функции
Наверное, можно в тех случаях, где поддерживается alloca и n меньше некоторой величины (предлагаю размер страницы для платформ со страничной памятью), то выделяем через alloca на стеке.
> C (added in C99 as a conditional feature which implementations aren't required to support[1]; on some platforms
При замене T[] на std::vector<T> приходится строки, содержащие
T *t=a заменять на T*t=&a[0];
Потому что нехуй.
> T*t=&a[0];
Ужас какой. Можно узнать зачем все это?
std::fill
> скопировать из вектора в видеобуфер
std::copy
Кстати, как константныей итератор кастануть в неконстантный?
Все-таки хочется выстрелить себе в ногу?
А вы знаете толк в сортах говна...
Вектор для хранения картинки плохо подходит: её размер известен и стоит использовать массив.
Охуенное решение.
Как внутренность класса SoftwareSurface - сойдет.
bitblt
fastblt
и тому подобное с аппаратной поддержкой блитинга из памяти в видеопамять
я как то привык к студийному stl, что считал за должное - на &v[0] пустого вектора всегда жди беды
а это оказывается _SECURE_SCL мне так всегда подсирает
насчет вменяемого - как раз удобно передавать в сишные вызовы (..., &v[0], v.size(), ...), а там уже пускай библиотека в зависимости от size() пляшет
А насчет передачи - ничего не имею против. Как я писал ниже "корректный код, зная, что ему передали указатель на массив длины 0 не будет его трогать".
Да ещё и пытаться передавать дырку от бублика куда-то там?
Но мне чаще встречались такие, которые требуют выполнения предусловий. Корректный указатель, положительное число и т.д.
P.S. Это может быть связано, конечно со сферой именно вычислительной. Функция сама не выполняет никаких проверок, потому что это может снизить производительность. Ведь неизвестно сколько раз её вызовут... 10 или 450 000.
Проверки предусловий безусловно нужны. Но зачем проверять корректность указателя при size==0? И, кстати, как проверить корректность указателя в не managed куче?
> Функция сама не выполняет никаких проверок, потому что это может снизить производительность.
Я понимаю. Но допустим этой функции передали data=NULL и size==0. Зачем код будет трогать элементы data, если size==0. Можно пример? (Случай, если функция требует массив ненулевого размера отбрасываем, т.к. тогда ошибка не в том, что функции передали мусор в указателе, а в том что size==0).
Передаём два массива double in* double out* и два размера size_t n size_t m
Какой-то массив не определён и один из размеров равен нулю.
Функция не будет думать, что там что-то нулевое, а начнёт обращаться к элементам n*j + i. И будет бум!
Проверить на корректность указатель нельзя никак. Разве что dynamic_cast в некотором роде проверяет корректность указателя. А вообще никак. Операции передачи указателя всегда доверенные. Тот, кто передаёт, должен быть уверен в том, что указатель верный. Обыкновенно он уверен, потому что пред и пост условие содержит правило "указатель верный".
double const * in - только его и можно передать пустым
соответственно его размерности n и m будут в точности = 0, и циклы [0..n), [0..m) не сделают ни одной итерации
double * out - ну так он не имеет права быть меньше in
бум не случится
Меня просили пример, куда приходят некорректные данные, но допускаются нулевые размеры.
Вы забыли инициализировать вектор.
Ок. Его size = 0. Вне зависимости от того что я передам в функцию - правильный указатель на пустой массив или любую хуйню - произойдет краш. Хотя в случае с правильным указателем он скорее всего не произойдет. Что еще хуже.
зачем ей max(m,n)
обсуждается транспонирование?
Но мне хотелось притянуть так, чтобы и ноль можно было записать.
Bormand, успокойтесь. Понял уже я, что ты про другой ноль.
Вот чего конкретно хочется вам сказать про столбцы и строки? Что столбцы и строки -- это представление ковариантность-контрвариантность? Возьмите с полки пирожок.
Я просто поражаюсь тому, как умеют местные говорить не по делу.
Хорошо. Пусть у нас будет особая, мнимая матрица 0*m. Если задача этого требует - пусть будет. Соответственно у этой матрицы нет элементов. Раз у нее нет элементов - лезть к ним нельзя. Иначе UB. Да и никто лезть не будет. Даже если, к примеру, у нас на входе матрица N*N, а на выходе получается (N-1)*(N-1) и N==1 (N==0, конечно, нельзя, выход за область определения). Поэтому я могу передать в качестве данных хоть мусор, хоть валидный указатель хоть NULL. Функция даже не заметит.
С чего это вдруг у мнимой матрицы нет элементов? Элементов у неё m, просто она мнимая.
И уже понятно, что речь шла о валидности предусловия size()==0. Просто по определению: если size()==0 функция на нулевом массиве должна достигать корректного постусловия. Следовательно, не может разименовать указатель, что приведёт к неопределённости. И потому не важно, что это за указатель.
Ясно
Кажется понял, к чему вы клоните - (0,m) и (n,0) специальные матрицы, у которых данные хранятся так же как и у матриц (1,m) и (n,1), но алгоритм обращается с ними по-другому? Но этот пример вообще не имеет отношения к "А с чего бы вам получать адрес первого элемента пустого массива?". Здесь массив не пуст (за исключением случая m==n==0), в нем есть max(m, n) элементов.
И тем не менее, пример наглядно показывает, что не всегда можно передать в функцию дырку от бублика и надеяться, что она её проглотит и сможет разрешить.
Как я написал в своём комментарии: это хорошо, если может, но сам я с таким не сталкивался.
Я же писал выше "Случай, если функция требует массив ненулевого размера отбрасываем, т.к. тогда ошибка не в том, что функции передали мусор в указателе, а в том что size==0"
И слава богу, если будет бум, а не вернется неведомая хуйня из неизвестной области памяти.
Так по С++11 копирования не будет, если аллокаторы совпадают. O(1)
Так тоже:
И так (но уже даже до стандарта С++11):
Рассмотрим все случаи, когда дырка от бублика не будет проглочена. (Пусть функция принимает массив переменной длины data и размер size).
1) size == 0 не входит в область определения функции - имеем UB в любом случае, хоть в data дырка от бублика, хоть NULL хоть валидный указатель.
2) size == 0, входит в область определения функции, но функция все равно лезет к элементам data. С вероятностью 146% в этой функции допущена ошибка, и она и при size>0 лезет за границы массива.
3) size == 0 входит в область определения функции, функция не лезет к элементам data, но передает ее другой функции, которая к ним лезет - проблема рекурсивно сводится к первым двум пунктам.
Во всех трех случаях UB присутствует независимо от того передам я туда NULL, валидный указатель или мусор. Причем валидный указатель только усугубляет проблему, и вместо краша программа может выдавать неправильный ответ.
Поэтому спор о том, можно ли передать &a.front() (возвращающий NULL или мусор для пустого вектора) и a.size() в функцию считаю закрытым. Вердикт - можно.
В нём передаются корректные входные параметры скалярного типа и неверный указатель, проверить это невозможно. И получается бум!
Он никак не связан с size()==0.
если беспокоишься за засорение пространства имён, попробуй обернуть в анонимный неймспейс
14.3.1 Template type arguments
2. A local type, a type with no linkage, an unnamed type or a type compounded from any of these types shall
not be used as a template-argument for a template type-parameter. [Example:
—end example] [Note: a template type argument may be an incomplete type (3.9). ]
в с++11 кое-что могло поменяться по этому поводу
14.3.1 Template type arguments
1 A template-argument for a template-parameter which is a type shall be a type-id.
2 [ Example:
— end example ] [ Note: A template type argument may be an incomplete type (3.9). — end note ]
А как сделать такое?
ты хотел, может:
а студия всеядна
Да, мне это было надо (чтоб работало в т.ч. и для классов с конструктором с параметраме).
На const& я забил, оно вынуждает писать const в методах класса, просто & плюётся, что это типа нестандартное расширение, а классы, которые я буду у себя передавать, всё равно слишком мелкие, чтобы копирование со стека могло замедлить работу, да и оптимизации компилятора стопудов есть на этот случай.
вряд-ли тебе на самом деле нужно менять временный объект
2. Писать const во всех методах не хочу.
ПС поставил плюсик ^_^
ты уж определись, либо ты меняешь объект (тогда ломай голову над корректной передачей необязательного & - подсказка - аналог boost::optional, либо указатель вместо ссылки), либо ты просто к нему обращаешься за чтением - тогда временный объект const & по умолчанию вполне приемлем
А передавать A() по копии кто мешает-то?
Ёпт, убрал расширения языка из опций, так он ругнулся на скачанный мной из инета stdint.h
c:\Users\TarasB\Documents\Visual Studio Projects\units\stdint.h(247): fatal error C1071: unexpected end of file found in comment
http://ideone.com/cKrSH
Но нахуя?
По & свежесозданный A(1) передавать нет никакого смысла (да и gcc не даст) - т.к. вызывающая функция все равно не сможет им воспользоваться. Если хочешь изменить в функции объект и воспользоваться результатом - опиши его как "A a(1);", а не создавай прямо в вызове.
По значению - тоже нет смысла, т.к. зазря вертим конструкторы - создаем объект, создаем копию, грохаем объект... Компилятор, возможно, додумается выкинуть лишние операции, но не факт.
Свежесозданный объект имеет смысл передавать только по const &.
Так что раз можно, то збс
Эээ, а зачем тогда передавать этот, хм, unit type, в функцию?
а, следовательно, нет никаких тарасо-проблем "ну там же надо const расставлять, а я крутой программист, мне это не нужно"
Другое дело - если в нем есть виртуальные методы, и Тарас хочет сделать что-то типа такого:
http://ideone.com/Ezw24
в любом случае, раз он собрался передавать как копию, он (вероятно) понимает, что base b = derived; сделает ему копию именно типа base и никакой полиморфизм тут уже работать не будет
и да, где виртуальный деструктор, блеать?
Все, месяц каторжных работ на асме. Каюсь. (Хотя в этом примере деструкторы все равно отработают не виртуально).
попробуй скажи статическому методу const, посмотрим, оценит ли компилятор шутку
(на всякий случай - я про конст, говорящий о том, что метод не меняет данные объекта)
И какая разница, статический или динамический?
а для класса понятия const не существует
поэтому компилятор обязательно выдаст тебе ошибку
ну и, несложный вывод, что статический метод можно вызвать не только у константного объекта, но и вообще без объекта
опять ты за старое
не парься, он уже знает что делать
А переголова из-за передачи неиспользуемого this в нестатическую функцию стопудов уберётся.
Удачной компиляции :-)
main.c: В функции «evil_timeout»:
main.c:89:24: ошибка: параметр «data» не используется [-Werror=unused-parameter]
Имхо лучше проявлять дисциплинированность, и в более-менее удобные моменты устранять ворнинги, нежели тратить время на бесполезный фикс ворнингов в коде, который минут через 10-15 будет выпилен нахрен или отрефакторен.
Отсутствие переноса строки после {?
};?
я знаю ворнинг "файл обязан заканчиваться newline"
на днях я так и не поборол его в гцц 3.x в новом проекте - везде где можно уже поставил, все равно где то у него не вяжется
Я её не включаю правда.
У нас в проекте есть Sonar, который занимается такой хернёй, и менеджмент заставляет нас фиксить "неправильно" названные переменные и слишком много условий в ифах. А то, что архитектура в жопе, и код надо рефакторить нахрен, это мало кого волнует.
помню, я тогда сильно матерился вместо "mixed tabs and spaces" тоже была фатальной ошибкой, ломающей билд.
И не успокаиваюсь, пока в коде есть warningи.
Можете показывать на меня пальцами, но у меня при сохранении Eclipse не только форматирует код (да-да, мне лень все пробелы, табы выравнивать ручками), но и сам подставляет this. для полей и методов, а для неизменяемых переменных и полей сам пишет final.
Кстати, пришлось тут поработать в VS 2008 с c# (помнится, студия - давняя гордость дотнетчиков), так вот, Idea мне кажется гораздо более удобной и стабильной (студия регулярно падает в дебаге). В VS по умолчанию даже дифф-тула нет, а плагины для того же свн тормозные и глючные. Походу всё работает до тех пор, пока всё идёт по плану мелкомягких (TFS и т.п.), шаг влево - вправо - расстрел, прыжок на месте - попытка улететь.
Без Resharper на VS вообще смотреть даже не хочется.
[/holywarmode]
Говно, но бесплатное и с кучей плагинов. Есть мнение, что IBM просто не способен на производство продуктов, которыми удобно пользоваться.
Idea сама выравнивает, предлагает упрощать выражения и подсвечивает слишком сложные конструкции (try внутри цикла считает сложной, к примеру, но уж никак не 4 условия в ифе). Даже емакс выравнивает строчку при нажатии Enter или ввода точки с запятой (можно ещё таб нажать, если нужно форсировать выравнивание). Форматирование, кстати, Sonar не ловит, в коде полно вермишели из табов и пробелов.
Ну нету в этом блядском С++ шаблонов, принимающий ФУНКЦИИ в качестве параметров. В Аде вот блин с 83 года есть, а в С++ нету. Поэтому приходится передавать класс.
Так?
http://ideone.com/RyeWm
Компилятор хоть догадаться и заинлайнить сможет? Гарантируется ли?
Выхлоп гцц на О2:
зачем шаблониться?
если ты хочешь передавать что-нибудь, что имеет operator (), то тебе нужно либо делать функторы (работает в голом с++03), либо boost::function (std::function)
я не знаю что там умеет твой калеченный андроид ндк, но в принципе boost.function/boost.bind полностью инлайновый и должен работать
Тебе такого инлайна мало?!
Это не инлайн. Я не очень рублю АТТ синтаксис, но судя по отсутствию скобок, это прямой вызов, а не по указателю, и на том спасибо. Но это не то, что мне надо
Где ты тут вызов увидел. Гцц превратило std::cout << run<test>(5, 6) в тупо std::cout << 13. Что как бы намекает на инлайн через 2 колена.
http://bit.ly/MZmirQ
компилятор оставил тела функций g и f, потому что они должны быть видны в объектнике
а вот более наглядно:
http://bit.ly/LUDOhz
Да. _ZNSolsEi вроде как он и есть.
Вы так говорите, как будто это что-то плохое.
Ссылка на созданный конструктором объект.
Все параметры шаблона должны разруливаться на этапе компиляции. Так что походу никак. Но может быть defecate-plusplus расскажет что-то, что я не знаю...