LINUX.ORG.RU

Избранные сообщения mentalmenza

Между молотом(Android) и наковальней(iOS). Какие могут быть стратегии у тех, кто захочет отнять у этих двоих часть рынка?

 баланс, , ,

Вообще, Android + iOS это просто идеальная «сладкая парочка». Android больше берет числом продаж(хотя конечно, есть и дорогие устройства), а iOS - их прибыльностью, благо устройства Apple позиционируются как «элитные»(оставлю в стороне вопрос, насколько это обосновано).

Если бы Android с iOS были бы биологическими видами, то я бы сказал, что они очень удачно подобрали эволюционные стратегии. Они не мешают друг другу(по крайней мере, в теории), и любой «третий» окажется в ситуации а-ля Сцилла и Харибда, подвергаясь просто ЧУДОВИЩНОМУ, без преувеличения, прессингу с обеих сторон.

В связи с чем, мне было бы очень интересно рассмотреть возможные стратегии тех, кто все-таки пытается «пролезть»(впрочем, умозрительные стратегии без привязки к кому-либо конкретно тоже приветствуются). У кого какие идеи?

Вот мои наблюдения.

1.Windows Phone. Во-первых, пытаемся паразитировать на более успешном конкуренте(патентные отчисления с Android). Во-вторых, так как нам доступны огромные ресурсы, вбухиваем их по полной программе, ибо мы можем себе позволить отчаянно демпенговать и выходить в минус с расчетом на то, что в «светлом будущем» это окупится с лихвой.

2.Replicant. Находим некую весьма специфическую(пусть может быть и очень узкую) группу пользователей, которые сильно неудовлетворены как Android, так и iOS. В данном конкретном случае это пользователи, которые по тем или иным причинам хотят использовать ОС с как можно меньшим(в идеале нулевым) количеством проприетарного ПО.

Как думаете, какие еще возможны стратегии? Например, может быть FirefoxOS будет продвигаться под какой-то еще, своей уникальной стратегией?

Deleted
()

Книжка по глубокому жаваскрипту

 in depth, ,

Посоветуйте книжку по глубинам жаваскрипта!

Т.е. не референс по апи (оно на сайте мазилы), а что-нибудь типа философии, организации/паттернов, деталей реализации виртуальной машины, итп. Н-р очень интересно, как работает сборка мусора, как писать нетормозящий жирный код, как симулировать многозадачность на браузерных реализациях, итп.

Если вы произносите JavaScript как CoffeeScript, неплохо бы получить про него то же самое, особенно про борьбу с Недожсом с помощью сабжа. Ну и ссылку на ваш инстаграм, конечно!

Спс

stevejobs
()

рекурсия и итерация

 итерация,

Приветствую всех.
Вопрос мой довольно праздный, и возможно кому-то покажется бесполезным. Тем не менее. Не кажется ли вам, что то что сейчас понимается под этими 2 терминами несколько не соответствует действительности. Вот что я имею в виду. У нас есть рекурсивный процесс, он интуитивно понятен на примерах трельяжа, стихотворения «у попа была собака» и пр. В программировании он может быть выражен 2-мя способами: с помощью итерациии и с помощью того, что принято называть рекурсией
На концептуальном уровне, это, безусловно, неверно, поскольку мы имеем 1 процесс и 2 способа его реализации, и называть способ реализации процесса самим процессом не совсем правильно. Таким образом, я хочу сказать, что выражение «рекурсивная реализация алгоритма» значит то же, что «рекурсивная реализация рекурсивного алгоритма» - бессмысленный набор слов, и, при этом, сама реализация, собственно не имеет ничего общего с рекурсией
Хотелось бы попросить воздержаться от постов вроде «Ты не знаешь язык X и математическую теорию Y, поэтому ты чмо». Если то, что я написал кажется вам глупостью, просто проходите мимо.
Итак, ваши мнения, Господа.

anonimous
()

Чистые функции

 ,

Долго не мог понять, каую же магию таят в себе чистые функции, и вот наконец проблеск:

(and state1 state2 (change-state)
; этот код может изменить состояние
; мы можем написать этот код в более привычно-костыльной форме:
(if (and state1 state2) (change-state))
; суть от этого не меняется
; этот код основывается на сайд-эффектах и сам создает его
; оформим его в виде функции
(define code (lambda() (and state1 state2 (change-state))))
; теперь мы можем менять состояние делая вызов функции - мы добились просто более краткой записи кода, но пока у нас нет никакой абстракции.
; ту же функцию мы могли бы записать так:
(define code (lambda() (and (get-state1) (get-state2) (change-state))))
; это ничего не меняет, ненужное усложненние
; eсли в нашем приложении имеют значение только эти 3 состояния, то такой код нас устроит во всех отношениях
; однако если у нас есть разные программные объекты которые пользуются тем же принципом, "если это и это тогда это", мы должны обобщить это в виде функции:
(define sup-code (lambda(x y) (and (get-state x) (get-state y) (change-state))))
; данная абстракция не использует напрямую сайд-эффекты, но все еще сама является источником его, исправим это
(define sup-code (lambda(x y z state) (and (get-state x) (get-state y) (z state))))
; мы получили абстракцию которая сама может быть объектом манипуляций, и до тех пор пока она является объектом манипуляций, она не вызовет сайд-эффектов. Если же она будет вызвана, посредством своих аргументов, она создаст сайд-эффекты. Иными словами мы получили СЛОЙ АБСТРАКЦИИ!!!
Таким образом, это банальная абстракция, в некотором смысле, инкапсуляция. Идея вполне себе простая и естественная, в плане расширяемости и преодоления сложности. Собственно вопрос в том, нахрена делать из этого культ, и городить какие-то типы, особенные языки и представлять это как науку посвященных (я имею в виду, что в литературе «постижение» обычно начинается с матанов). Или я неправильно понимаю идею чистоты функций?

anonimous
()

Есть ли для CL аналог стандартной библиотеки?

 ,

В общем ищу аналог питоновских батареек, такое есть вообще?

deterok
()

Выражение и инструкции

 глупые споры, ,

Навеяно обсуждением новой версии компилятора D в новостях.

Начался спор, как я понял, с вопроса о нужности явного ретурна, но мне кажется, что это лишь следствие более общего(и интересного) вопроса: «разделять ли при проектировании ЯП понятия выражение и инструкция или же считать все выражением?».

forCe
()

Y-комбинатор

Заглянул сегодня в вики по поводу сабжа и увидел следующее определение:

Y=/f.(/x.(f(x x)) (/x.(f(x x))))
Не закралась ли тут ошибка, ведь после получения f мы должны вычислить аппликацию в которой присутствует некий x, а откуда ему взяться?

new_1
()

КОМПИЛЯЙ!

Навеяло вот этой темой , особенно феерической растановкой точек анонимуса в конце треда. Но сейчас не об этом.
Не для кого не секрет, что сейчас вся разработка заточена на компиляцию, а как следствие, предпринимаются титанические потуги разработать некую систему синтаксической проверки корректности программ. Отсюда такие монстры как хаскель. Я оставлю в стороне тот вопрос, что современные вычислительные мощности позволяют быстро выполнять интерпретируемые проги, и во многих случаях даже эффективней, но всемпофик - это тема другого разговора. А в данном треде, я хотел бы узнать ваше мнение по поводу вот какого соображения: не для кого не секрет, что Геделем была доказана принципиальная невозможность доказательства чего либо, если уж на чистоту, он вообще опустил математику, до уровня бесполезной игрушки. Но даже без этого, на бытовом уровне мы можем понять, что никаких «математических доказательств» быть не может.
Что имеют математики в своем арсенале когда они пытаются втюхать нам свое доказательство? Индукцию и дедукцию, вестимо. Остановимся подробней на индукции: «Если все предыдущие слоны которых я видел были серого цвета, значит все следующие которых я увижу будут тоже серыми», иными словами, если баба Авдотья в своей деревне видала только бородатых мужиков, стало быть бритых нету. Доказано. Теперь пример дедуктивного рассуждения, которое считается 100% надежным: «Поскольку все слоны серые, этот слон тоже серый». Иными словами: «Авдотья, у Ваньки есть борода? - есть конечно - а откуда ты знаешь, ведь ты его никогда не видела? - дык все мужики бородаты» Доказано 100%.

Мне просто интересно становиться иногда, почему люди, с виду нормальные, в частности прогеры, позволяют так легко себя надувать? Или действительно произошел какой-то качественный сдвиг в развитии Homo sapiens? Как это объяснить кроме как вырождением чел расы?

Перемещено mono из development

anonimous
()

обучение программированию рисованием

 ,

Вспепомнящий all,

а ты помнишь, BASIC с его circle, line, cls и так далее?
И как было интересно учить основы программирования на примере задаче типа - нарисовать катящегося по экрану колобка или звёздное небо с появляющиемеся звёздами-точками...

Короче, сам не программлю на Си профессионально (хотя программлю на 3х других высокоуровневых ЯП), но надо приобщить одну тян к этому гадкому делу, на примере вот таких вот задачек.

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

Что-то простое и доступное студенту первого курса, чтобы на примере задачек типа «нарисуй точку и заставь её двигаться по синусоиде» подвести к изучени циклов и тп. Не обременяя выскоуровневыми API к X.

Den0k
()

Ruby не в веб-разработке

 , ,

Всем известны сильные позиции Ruby в веб-разработке. Как минимум все работает, компании запускают веб-приложения, деньги зарабатываются.

Как насчет вне веба?

P.S. Например близжайший конкурент - Python захватил наверно пол линукс десктопа, широко используется как встраиваемый язык, а так же очень известен в научных кругах, data mining, data analisys. И это не смотря на тоже очень сильные позиции в веб сфере.

vertexua
()

Почему web так убог?

 , ,

Собственно давно задавался этим вопросом. Я сам последнее время работаю с вэбом и почти каждый день спрашиваю себя - почему здесь всё настолько криво. Почему спросил сейчас? Вот сижу и пишу стопяцотый велосипед который сделает удобным вывод форм на страничку избавив от всего этого хлама типа select, textarea, checkbox(value) и прочего сказочного поноса. Конечно пишу на пыхе потому что целевой фреймворк, как и подавляющее большинство, на пыхе. И тут вот такая тема - Python или PHP, или вообще Pascal?

Невольно задаешься вопросом, почему все эти люди которые создали всякие html, php, css и прочие js (возможно к последнему притензии мои и зря), смогли вывести это в мэйнстрим? Почему мэйнстримом де-факто стали настолько убогие и кривые стандарты и технологии?

P.S.
Мнения тех, кто считает что все нормально и не видит глобального ада, не очень интересно. Интересно именно чем думали создатели этого.

Suntechnic
()

Тупой вопрос про кеш цпу

Здорово, мужики. Ща я расскажу вам небольшую предысторию.

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

Далее, сам рендерер может быть такой:

1) Для каждого пикселя на экране пускаем луч, который обходит это дерево с корня до листов, и, если есть пересечение, ставим точку на экран (я использую SDL и пишу в surface->pixels)

2) Подмечаем, что для близких лучей (мало отклоняющихся) путь от корня дерева до листа с данными почти одинаков (например root->a->b->c->d и root->a->b->c->e) и начинаем поиск с листа, возвращаесь, если надо, к корню.

И вот вопрос: для второго случая надо записывать в surface->pixels элементы не один за другим, как в таком коде:

int i,j;
int p = 0;
for (i=0; i<surface->w; i++)
{
    for (j=0; j<surface->h; j++)
    {
        *((Uint32*)surface->pixels+p) = calc_color();
        p++;
    }
}

а, скажем, разбивая экран на квадратики, где такая путь обхода меняется лишь незначительно. Но с другой стороны, к элементам pixels придется обращаться не один за другим, а как-то так:

int i,j,k,l;
for (i=0; i<surface->w/SQUARE_LEN; i+=SQUARE_LEN)
{
    for (j=0; j<surface->h/SQUARE_LEN; j+=SQUARE_LEN)
    {
        for (k=0; k<SQUARE_LEN; k++)
       {
            for (l=0; l<SQUARE_LEN; l++)
           {
                *((Uint32*)surface->pixels+(i+k)*width+j+l) = calc_color();
            }
        }
    }
}

Сильно ли это скажется на производительности из-за промахов в кеше? Или какие варианты могут быть, чтобы локальность и в смысле обхода дерева (в двухмерном пространстве) сохранить, и в смысле записи в pixels.

Мальчики, выручайте, ога?

Vikusya
()

Что читать по BSD kernel?

Извините что к вам обращаюcь... но что почитать по программированию для BSD-ядра (в любом варианте, хотя лучше FreeBSD)? http://www.freebsd.org/doc/en_US.ISO8859-1/books/arch-handbook/ как-то не особо полон. Желательно наличие книг в легальном доступе. Сурсы не предлагать, это само собой.

Я правильно понимаю по уже прочитанному, что механизм модулей там тоже есть, и для их сборки все ядро перекомпилировать не нужно?

PS Пишу учебное пособие. В ходе написания введения пришел к выводу, что надо либо найти аргументы "почему линукс лучше бзди для сиспрога в ВУЗе", либо рассмотреть и BSD тоже (место, думаю, позволяет).

PPS Нет, ничего нового в пособии не скажу, просто надоело каждому читать вслух и с переводом LDD и иже с ними :(

>>> Подробности (Invalid URL, no host part!)

sv75
()

Начинаю учиться с нуля

 ,

Итак, узнал на ЛОРе, что для этого нужно выкинуть из головы всю кашу и начать учиться с нуля строго последовательно и систематично. Прочитал в какой-то теме, что нужно начать с Фихтенгольца. Но я что-то не наблюдаю там основ. Я не знаю, что такое число, рациональное число, множество, что означают все эти закорючки, откуда они взялись, почему именно такие закорючки, а не другие, почему их именно столько, а не больше и не меньше. И что это за слова такие «определение», «следовательно», «очевидно»? Их можно вставлять в текст от балды?

В общем Фихтенгольц не подход для начала с нуля, нужны какие-то более фундаментальные учебники. Вопрос - какие?

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

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

CoolProgrammist98
()

Как стать разработчиком ядра Линукс: шаги?

добрый день!

Могу я попросить совет, что освоить и на чем попрактиковаться, какие книги и проекты изучить, чтобы расти в сторону системного программиста под Линукс?

Посмотрел вакансии и выяснил, что требования примерно такие:

XXX приглашает на работу Linux Kernel Developer Требования: хорошие знания ANSI C; опыт программирования на уровне ядра Linux ; знание архитектуры Linux и умение ориентироваться в исходных текстах ядра; владение базовыми средствами разработки под Linux (gcc, binutils, gnumake, инструментарий отладки системного ПО); опыт написания драйверов или программных компонентов DSP;

Примерно для себя наметил:

1. Прочесть книгу по Линуксу. 2. Прочитать книгу по архитектуре компов и устройству ОС 3. Прочитать книгу по ядру Линукс 4. Выучить С по Кернигану 5. Осилить основы электроники и схемотехники. 6. Писать свои проекты и изучать чужой код - пока еще четко не выбрал, что именно. ???

Есть опыт только в написании сайтиков. Спасибо за советы!

podelkin
()

Нигде не берут на работу :( junior

 ,

7 дней откликов на вакансии компаний которые никогда не будут крупными пузырями. Когда нибудь они лопнут, только это облегчает мою ненависть за прошедшие семь дней. И так начнем по порядку о себе - знаю технический и разговорный английский на приемлемом уровне. Правда нигде не учусь так как считаю что российское образование это пустая трата времени. Хотелось бы найти работу junior программиста где интересно и здоровое общение.

Я гр. СНГ, 20 лет, переехал в столицу несколько лет назад.

Вот что я показал о навыках в резюме: Теоритеческое знание CSS, HTML(есть практика). А также C, Python + Django немного тестинга на selenium, смотрел исходники очень хорошего фреймворка для e-comerce - Oscar. PHP изучал давно но в связи критики со стороны гуру интернет программистов, не стал юзать. Сейчас изучаю bash, хочу писать супер скрипты для автоматизации и просто для удобства, очень удобно для инсталяции сервера в два клика. Предпочтительная ос Убунту. Есть опыт настройки гейм серверов. Расматривал также javascript + jquery. Очень хотелось бы попрактиковать себя в интересном проекте. Так как опыта в программировании очень мало, себя расматриваю как junior программиста. Пишу на vim с плагинами, очень удобная штука для быстрого редактирования текста, также хочу попробовать github.

Помогите, обьясните в чем дело, может я недочел что то. Но не может быть что никто не принимает мигрантов на работу.

P.S не судите так строго. мне 20 лет ничего более серьезного я из себя не имею.

Перемещено beastie из job

peace_duke
()

Linux Kernel Development, особенности работы

 , , ,

Интересуют особенности работы в этой области. У меня сложилось впечатление (вполне возможно, что неправильное, потому и спрашиваю), что всё что связано с линуксами, Си, ядром, драйверами и т.п., это такая стабильная область программирования. Т.е. не смотря на то, что знать надо много, но инструменты давно не меняются, новые технологии не появляются (или появляются не так часто в сравнении с вэбом).

arado
()

товарищ посоветовал «изучи C, а лучше Python» и я задумался...

 

да, почему бы и нет, ибо уже давно-давно не изучал никаких ЯП, только вот я уже достиг такого возраста, что не то лень, не то «не нужно»: то есть, когда возникает задача, любая, какая может возникнуть на экзотичном десктопе, я успешно костылю ее имеющимися средствами.

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

думаю таки взяться за C, ибо романтик, а на нем хакеры пишут эксплоиты. :)

сейчас я знаю mSL (mIRC Scripting Language), PHP и Bash.

mIRC - второй родной, как говорится. на нем я познавал протоколы, писав собственные реализации ftp сервера, http сервера (с поддержкой CGI для Perl, PHP, Python, Ruby, TCL и так же BitTorrent Tracker), irc сервер, радио-вещатель (стрим mp3 файлов), ковырял заголовки файлов с целью вытащить из них инфу.. да чего я только не делал. пытался даже dns сервер, но не осилил.. а клиент а-ля nslookup таки написал. и многое, многое другое..
так или иначе, тыкни пальцем в любой популярный протокол, - я его ковырял и/или реализовывал, гы.
пруфы конечно могу предоставить, за давностью лет ничего локально не сохранилось (с переходом на линукс, а мирк - проприетарный чятик для офттопа). но все это я выкладывал на сайтах mircscripts.org, hawkee.com и других..

PHP/PostgreSQL - наговнодил бложик.

на Bash с целью его изучения писал пакетный менеджер.

но вернемся к C. нужно ли? с учетом того, что есть один LFS которому бы не помешала рука C-программиста чтобы его допиливать и/или патчить софт.

а к высокоуровнему Python'у душа не лежит, ибо зачем, если есть куча других альтернатив (PHP, который уже знаю).

дабы не разводить флейм, посоветуйте, стоит ли _в свое удовольствие_ браться за изучение C, и если да, то пульните какой-нибудь вводной документацией объясняющей зачем нужны еще какие-то autoconf, automake и прочие, а не достаточно обойтись одним gcc и баш-скриптом автоматизирующим сборку? и ткните в какую-нибудь онлайн-книженцию для ньюфага. :3

Spoofing
()

Тёмные углы C и C++

 ,

Изначально даный пост предназначался для habrahabr, но местные модераторы его не пропустили без объяснения причин:

Увы, ваш топик «Тёмные углы C и C++» не был одобрен и не попал в общую ленту. Причин этому может быть много, но просим не терроризировать службу технической поддержки, так как там вашу статью даже не видели. Расстраиваться тоже не стоит - попробуйте опубликовать что-нибудь еще.

С уважением, Хабрахабр

В связи с этим выкладываю его сюда.

Я, как и многие из вас, работаю программистом. Официально моя должность не привязана к какому-либо конкретному языку программирования, что, кстати говоря, прекрасно, ведь для каждой задачи должны быть свои инструменты. Но довольно часто выбора просто нет (например, из-за особенностей реализации той или иной платформы), в связи с чем подавляющее большинство моих проектов пишутся на C++.

Я не гуру C++. Я не могу похвастаться тем, что с уверенностью распознаю любую шаблонную конструкцию данного языка или возьму и вспомню, что возвращает какая-то редко используемая мной функция из стандартной библиотеки без помощи документации.

Думаю, вы со мной согласитесь, что C++ — язык с очень высоким порогом вхождения. Серьёзно! Я изучаю этот язык уже больше 3 лет, и практически каждую неделю открываю в нём что-то новое и удивительное. Именно об этом «новом и удивительном» и пойдёт речь в данной статье.

За то время, пока я изучал C++, у меня потихоньку накапливались интересные задачки, сниппеты и просто необычные куски кода, которыми я делился с коллегами по работе и знакомыми. У нас даже появилась своего рода традиция — каждый рабочий день с того момента, как я пришёл в компанию, я выкладывал по две новых задачки, которые мы старались по возможности обсудить в перерывах. Постепенно их набиралось всё больше и больше, пока, наконец, я не стал забывать некоторые из них. Именно в тот момент я решил предпринять попытку составления сборника так называемых «тёмных углов» C и C++. Я собрал воедино все те куски кода, что видел до сих пор, дополнил их цитатами из различных стандартов и продолжил копить свою «коллекцию». Изначально моей целью было собрать вместе всего 100 задачек, но я и оглянуться не успел, как их стало уже 200, 300 и вот теперь 400. На самом деле, их даже больше, но на данном этапе я решил ограничиться именно этим количеством.

Итак, представляю Вашему вниманию книгу «C and C++ Dark Corners». Конечно, назвать её книгой можно с натяжкой, ведь это, как я уже и сказал, сборник интересных и для кого-то малоизвестных мест C и С++.

Не откладывайте её в сторону после пары-тройки вопросов, ответы на которые Вы уже итак знаете — я уверен, что хоть какие-то из них заставят Вас задуматься, а ответы на другие могут удивить и даже шокировать.

В качестве примера приведу несколько вопросов из книги:

97. Что попадёт в stdout в результате выполнения след. кода и почему?

#include <iostream>
#include <memory>

#include <boost/smart_ptr/scoped_ptr.hpp>

class Foo
{
public:
 ~Foo() { std::cout << "Foo::~Foo() \n"; }
};

class Bar : public Foo
{
public:
 ~Bar() { std::cout << "Bar::~Bar() \n"; }
};

class Baz : public Bar
{
public:
 ~Baz() { std::cout << "Baz::~Baz() \n"; }
};

int main()
{
 std::cout << 1 << '\n';
 {
  Foo* instance = new Baz;
  delete instance;
 }

 std::cout << 2 << '\n';
 {
  std::shared_ptr<Foo> instance(new Baz);
 }

 std::cout << 3 << '\n';
 {
  std::shared_ptr<Foo> instance(false ? new Bar : new Baz);
 }

 std::cout << 4 << '\n';
 {
  boost::scoped_ptr<Foo> instance(new Baz);
 }

 std::cout << 5 << '\n';
 {
  std::unique_ptr<Foo> instance(new Baz);
 }

 std::cout << 6 << '\n';
 {
  std::auto_ptr<Foo> instance(new Baz);
 }
}

A: Первый случай уже обсуждался ранее – здесь UB в чистом виде (как правило, это приводит к тому, что не будет вызван деструктор производного класса).

Второй случай выдаст на экран следующее:

Baz::~Baz()

Bar::~Bar()

Foo::~Foo()

Почему? Что произошло? Ведь мы же ясно видим, что деструкторы у данных классов не являются виртуальными. Или это один из частных случаев UB? На самом деле, тут всё вполне законно и должно работать так, как указано выше. Посмотрим в документацию к std::shared_ptr и boost::shared_ptr:

http://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr

Proper delete expression corresponding to the supplied type is always selected, this is the reason why the constructors are implemented as templates using a separate parameter Y.

http://www.boost.org/doc/libs/1_51_0/libs/smart_ptr/shared_ptr.htm

This constructor has been changed to a template in order to remember the actual pointer type passed. The destructor will call delete with the same pointer, complete with its original type, even when T does not have a virtual destructor, or is void.

Третий случай выдаст:

Bar::~Bar() Foo::~Foo()

Почему? Ведь мы только что обсуждали поведение std::shared_ptr! Что тут не так? Вспомните поведение тернарного оператора в C++ — он требует, чтобы второй и третий его операнды были одинакового типа. Более того, каст от базового к производному касту без лишних действий не выполнить, в отличие от обратной ситуации:

#include <iostream>

class Base
{
};

class Derived : public Base
{
};

int main()
{
 Base* first;
 Derived* second;

 Base* foo = second; // Ok
 Derived* bar = first; // Error: invalid conversion from 'Base*' to 'Derived*'
}

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

#include <iostream>
#include <typeinfo>

template <typename T, typename U>
auto foo(bool b, T t, U u)-> decltype(b ? t : u)
{
 return b ? t : u;
}

int main()
{
 auto _1 = foo(true, 0, 'c');
 std::cout << typeid(_1).name() << '\n';
 auto _2 = foo(false, 0, 'c');
 std::cout << typeid(_2).name() << '\n';
}

Переменные _1 и _2 будут одного и того же типа – int.

Именно поэтому Baz в данном случае будет приведён к Bar.

4, 5 и 6 случаи ничем не отличаются от первого – здесь UB. Надо помнить, что поведение std::shared_ptr отличается от остальных умных указателей.

43. Зачем может понадобиться писать так

#define DO_JOIN(FOO, BAR) DO_JOIN1(FOO, BAR)
#define DO_JOIN1(FOO, BAR) FOO##BAR

вместо

#define DO_JOIN(FOO, BAR) FOO##BAR

A: Потому что препроцессор отработает конкатенацию не так, как того ожидал программист, в том случае, если в качестве аргумента(-ов) мы передадим в макрос DO_JOIN другой макрос:

#include <iostream>

#define DO_JOIN(FOO, BAR) DO_JOIN1(FOO, BAR)
#define DO_JOIN1(FOO, BAR) FOO##BAR

#define MY_MACRO 5

int main()
{
 std::cout << DO_JOIN(1, MY_MACRO) << '\n';
}

Output:

15

#include <iostream>

#define DO_JOIN(FOO, BAR) FOO##BAR

#define MY_MACRO 5

int main()
{
 std::cout << DO_JOIN(1, MY_MACRO) << '\n';
}

error: unable to find numeric literal operator 'operator"" MY_MACRO'

Получается, макрос MY_MACRO не успел раскрыться, в результате чего была попытка провести конкатенацию с 1 и MY_MACRO, что, разумеется, привело к ошибке.

ISO/IEC 14882:2011

16.3.1 Argument substitution [cpp.subst]

1 After the arguments for the invocation of a function-like macro have been identified, argument substitution takes place. A parameter in the replacement list, unless preceded by a # or ## preprocessing token or followed by a ## preprocessing token (see below), is replaced by the corresponding argument after all macros contained therein have been expanded. Before being substituted, each argument’s preprocessing tokens are completely macro replaced as if they formed the rest of the preprocessing file; no other preprocessing tokens are available.

44. Что попадёт в stdout в результате выполнения след. кода?

#include <iostream>
#include <stdexcept>

struct Foo
{
 Foo() { std::cout << "Foo::Foo()" << std::endl; }
 ~Foo () { std::cout << "Foo::~Foo()" << std::endl; }
};

void foo()
{
 Foo bar;
 throw std::runtime_error("Error");
}

int main ()
{
 foo();
}

A: Зависит от реализации.

// 1

Foo::Foo()

// 2

Foo::Foo() Foo::~Foo()

ISO/IEC 14882:2011

15.3 Handling an exception [except.handle]

9 If no matching handler is found, the function std::terminate() is called; whether or not the stack is unwound before this call to std::terminate() is implementation-defined (15.5.1).

Например, в документации к gcc сказано, что раскрутки стека не произойдёт:

The stack is not unwound before std::terminate is called.

Сборник выкладывается на бесплатной основе, желающим помочь каким угодно образом буду безумно признателен и благодарен. По любым вопросам, рекомендациям и пожеланиям Вы можете обращаться на мой электронный ящик nikita.trophimov@gmail.com. Буду рад услышать абсолютно любое мнение по данному поводу.

В книге ещё много чего можно и даже нужно дорабатывать. Обещаю, что если сообщество проявит хоть какой-то интерес к данному проекту, я продолжу развивать его согласно Вашим предпочтениям и пожеланиям, дополнять новыми задачками и исправлять ошибки. У меня есть много мыслей по поводу улучшения «C and C++ Dark Corners» — среди них добавление тематических разделов, workaround'ы для различных компиляторов и т.д. Главное, чтобы этот интерес был не только с моей стороны.

Жду Ваших положительных и отрицательных отзывов, рекомендаций и, конечно, новых задачек.

Внимательно ознакомьтесь с тем, что указано во «введении», и приятного чтения!

NikitaTrophimov
()

Бьёрн Страуструп выбирает борщ: «С++ почти так же быстр как Haskell»

 , , , ,

В дополнение к предыдущему посту о сферах применимости С++ и шедевральному посту об ооп (в данный момент продолжающегося обсуждением топологии Скотта).

(credits: гугля материалы о лиспе, случайно наткнулся на вот такой пост в ЖЖ, откуда я невозбранно изъял множество текста для написания этого сообщения.)

Итак, виновник торжества, этот пдф: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3449.pdf

Автор С++, преподобный Страуструп, и команда отчаянных друзей-борщевиков пишут новую библиотеку для диспетчеризации по типам с помощью внешней интроспекции. Это либа, написанная на шаблонах С++x11, и называется Mach7 (почти как вот эти няшные автомобильчики)

Вот, собственно, что так хочет видеть в крестах сам преподобный Бьорн:

int eval (const Expr& e)
{
    Match(e)
    Case(const Value& x) return x.value;
    Case(const Plus& x) return eval (x.e1)+eval(x.e2);
    Case(const Minus& x) return eval(x.e1)−eval(x.e2);
    Case(const Times& x) return eval(x.e1)∗eval(x.e2);
    Case(const Divide& x) return eval(x.e1)/eval (x.e2);
    EndMatch
}

В объектно-ориентированном языке без прямой поддержки алгебраических типов данных, тип, представляющий дерево выражения какого-то языка, обычно будет написан как абстрактный класс, с производными классами, реализующими более конкретные варианты.

struct Expr { virtual int eval () = 0; };
struct Value : Expr { ⋯ int eval (); int value ; };
struct Plus : Expr { ⋯ Expr& e1; Expr& e2; };

но более открытый (читай: расширяемый) дизайн заключается в другом:

По-настоящему открытые подходы опираются на дорогой тест на принадлежность к классу, комбинирующийся с деревьями решений.

Ну, то есть, хотим-то мы, наверное, как раз открытый подход, который подсмотрели из функционального программирования с его сопоставлением с образцом, но он слишком дорог с точки зрения CPU, если делать в лоб. Поэтому сделали Mach7, вот эту самую библиотеку на шаблонах, которая реализует открытый подход, но при этом не страдает по производительности, как если бы использовался тест на принадлежность к классу.

Насколько быстро теперь работает? Говорят, примерно как OCaml или Haskell:

Библиотека реализована как стандартный C++11 код с шаблонным мета-программированием и несколькими макросами. Оно работает примерно также быстро, как эквиваленты на OCaml или Haskell, и даже иногда приближается по быстродействию или даже становится быстрее написанного руками C++ кода, который использует Visitor дизайн-паттерн.

Ну это хорошо, что так быстро, как OCaml или Haskell. Вопрос, зачем при таком раскладе использовать C++, замнём для ясности.

Но дальше вообще прелесть идёт: критика паттерна Visitor!

Библиотека Mach7 и идеи в ней были мотивирована нашим неудовлетворительным опытом работы с различными C++-ными фронт-эндами и фреймворками для анализа программ. Проблема была не с самими фреймворками, но с фактом, что мы должны были использовать шаблон проектирования Visitor для того, чтобы смотреть, обходить и обогощать абстрактные синтаксические деревья целевых языков. Мы нашли Visitor-шаблоны неподходящими для прямого выражения логики приложения, удивительно сложными для обучения студентов, и часто более медленными, чем решения для обхода, написанные вручную. Вместо них, пользователи опирались на динамические приведения типов во многих местах, часто многоуровневые, таким образом предпочитая более короткий, более ясный, и более прямой код, нежели чем Visitor'ы. Соответствующий проигрыш в производительности был обычно незамечаем до более поздних стадий кодирования, когда уже было поздно что-то менять.

Ну можно поздравить C++, теперь можно на нём отдельные вещи писать почти так же коротко, ясно и почти так же быстро, как на OCaml.

В пдф по ссылке присутствуют графики сравнения перфоманса Хацкеля и Крестов, начертанные самим преподобным Бьорном, очень рекомендованные к просмотру для тех, кто еще не готов отречься от старых убеждений и перейти на новые.

Заметим, что не только Страуструп раскаялся в прошлом. Кармак с энтузиазмом рассказывает, как с головой погрузился в Haskell и Scheme, объясняет, почему хаскель невероятно крут и почему сегодня он бы, вероятно, сделал QuakeScheme вместо QuakeC. Он пишет на хаскеле порт wolf3D. (видео на ютубе — Quakecon 2013, обсуждение в толксах)

Пора задуматься о жизни, господа и дамы крестопоклонники.

stevejobs
()