Изменения

Перейти к: навигация, поиск

Участник:Qwerty787788/плюсы3сем

21 757 байт добавлено, 12:58, 5 мая 2021
binding arguments of functions
http://www.dreamincode.net/forums/topic/264061-c11-fun-with-functions/ - четкая статья, обо всем написано
//осилили
 
 
Поправьте, если я не прав (вполне возможно)
Суть в том¸ что если у нас есть функция, а мы хотим, например(?), уменьшить количество ее аргументов, то мы можем их забиндить! Т.е. если у нас есть функция
 
foo(double x, string y) {},
и мы сделаем
std::function<int(std::string)> foo_str = std::bind(&foo, 5.0, std::placeholders::_1);
то у нас появится новая функция foo_str с одним параметром стринг, второй параметр будет установлен как 5.0 (можно тутда записать переменную, тогда значение будет копироваться)
 
Анонимные функции
Это функции без имени, с которыми надо быть очень аккуратным. & по ссылке передает, = по значению
int arr[] = {1,2,3,4,5,6,7};
int sum = 0;
std::for_each(std::begin(arr), std::end(arr), [&sum] (int x) {sum += x;});
std::for_each(std::begin(arr), std::end(arr), [] (int x) {std::cout << x <<' ';});
 
=== зачем это надо ===
=== function objects ===
== type erasure ==
http://prograholic.blogspot.ru/2011/11/type-erasure.html
 
Поправьте, если я не прав!
type erasure это нешаблонный объект, который позволяет в себе хранить объекты любого типа, которые удовлетворяют заданному интерфейсу.
 
#include <gtest/gtest.h>
#include <boost/function.hpp>
#include "type_erasure.h"
typedef boost::function<int ()> sample_signature;
TEST(TypeErasure, DeclareInterface)
{
type_erasure t;
sample_signature s(t);
}
 
any_iterator – подобие boost::function, но для итераторов. Позволяет одному итератору етерироваться по разным типам данных
typedef adobe::any_iterator<int, std::bidirectional_iterator_tag> any_iterator_to_int;
А потом в любом случае если нужно итерироваться по интам мы можем использовать его.
=== polymorphic function wrapper (aka {boost,std}::function) ===
http://habrahabr.ru/post/159389/
 
=== any_iterator ===
http://thbecker.net/free_software_utilities/type_erasure_for_cpp_iterators/any_iterator.html
== signals (aka listeners aka observers) ==
что-то где-то произошло - вызывается какая-то функция обработчик
=== зачем это нужно ===
чтобы обеспечить связь между различными объектами. например кнопочку реализовать - по нажатию какое-то действие
=== примеры почему наивная реализация не всегда хорошо работает ===
Видимо наивная реализация - это колбеки (могу ошибаться)
Обратный вызов имеет два основных недостатка. Во-первых, он не является типобезопасным. Мы никогда не можем быть уверены что функция делает обратный вызов с корректными аргументами. Можно передавать function<> тогда будет типобезопасно. Во-вторых, обратный вызов жестко связан с вызывающей его функцией, так как эта функция должна точно знать какой обратный вызов надо делать. Также могут возникнуть проблемы, если в процессе обработки одного из коллбэков список подписавшихся на сигнал изменился. Если это вектор, это может привести, к примеру, к выполнению одного коллбэка дважды или пропуску одного из них. Для решения можно сделать из подписавшихся хороший двусвязный список.Также надо иметь в виду, что до обработки сигнала может быть возможно дойти прямо в процессе его же обработки, и нужно соблюсти reentrancy для обработчика.
=== понятие reentrancy ===
http://en.wikipedia.org/wiki/Reentrancy_(computing)
http://doc.qt.digia.com/qt/threads-reentrancy.html
=== пару слов про существующие реализации (boost::signals, boost::signals2, Qt Signals) ===
signals2 - thread-safe реализация signals
http://habrahabr.ru/post/50812/
 
http://www.rsdn.ru/article/cpp/signals2.xml
 
http://www.boost.org/doc/libs/1_39_0/doc/html/signals2/porting.html
== exception safety ==
Надо обязательно ловить ошибки в слотах, ибо иначе при испускании сигнала будут выполняться только те слоты, которые до пустившего исключение.
 
some link: [http://www.stroustrup.com/except.pdf] - слишком много
=== зачем это нужно ===
=== ошибки и как их можно обрабатывать (propagation to caller, assertion, logging, precess termination) ===
propogation to caller - это когда функция возвращаетможет быть реализован двумя методами: возвратом функцией кода ошибки или бросанием функцией исключения (и его отловом в вызывающем). Такое допускается для ошибок, что она отработала нормально не связанных с правильностью программы; чаще используется для перехвата обработки неправильных входных данных или код ошибки?с устройствами ввода/вывода. Срабатывание таких ошибок в программе считается нормальным, предполагается, что такая ошибка может быть корректно обработана. Assertion - "контрольные точки" в коде, срабатывание ассерта в программе обычно свидетельствует об ошибке в ее логике, правильности алгоритма. В идеале, такие ситуации в релизной версии не должны возникать вообще, поскольку описание ассерта имеет больше смысла именно для разработчика. В релизной версии лучше использовать лог-файл, а не грузить пользователя вещами, которых он, скорее всего, не знает. 
http://habrahabr.ru/post/141080/
 logging или журналирование - очевиднооптимальный для выпущенной программы способ обработки ошибок в логике кода - записать все мыслимые и немыслимые детали о ней в логфайл (или поток вроде stderr). Сам лог, в свою очередь, предлагается отправить разработчику для изучения. Может также быть использован самим же разработчиком для изучения особо безумных ошибок, непонятно от чего возникающих, для этого в лог можно писать все значимые действия программы.process Precess termination - ???крайний выход, свалить программу к чертям. Лучше избегать, если иное может, к примеру, нанести вред аппаратуре. Для отладки не годится, поскольку не дает деталей об ошибке сам по себе. На практике обычно используются комбинации. * Исключения, при разматывании стека целиком, приводят к аварийному завершению. Иногда производится печать в лог пути, пройденного исключением при разматывании стека.* Виндовский синий экран, предполагается, является этаким ассертом для выявления ошибки, после него снимается лог (иногда с дампом памяти), и происходит аварийное завершение.* Для случаев, когда произошедшая ошибка делает дальнейшую работу программы быссмысленной, сгодится ассертоподобное сообщение об ошибке и завершение программы.
== UNIX-signals (это не тоже самое что signals из пункта 3), hardware interrupts ==
== multithreading ==
=== зачем это нужно ===
Ну вроде бы очевидно: увеличить скорость выполнения программы. Однако, стоит понимать, что иногда скорость может даже уменьшиться (в интернете есть куча примеров).
Более подробно - это способ задействовать больше аппаратуры для выполнения алгоритма в современных компьютерах, которые хвастаются многоядерностью/многопроцессорностью - так достигается увеличение скорости выполнения. Это очень важно в бизнес-приложениях, а так как программист бизнес-приложений зарабатывает в два раза больше программистов других приложений, просто необходимо. Есть множество задач, которые хорошо делятся на несколько независимых друг от друга. Например, quicksort - после разделения элементов на группы, каждую из них можно сортировать независимо. Но тут важно не переборщить с его использованием, поскольку создание отдельного потока (thread, треда) тоже требует некоторых ресурсов, и сортировать в отдельном треде группы, скажем, по 2 элемента уже очень нерационально, это может как раз замедлить сортировку.
=== понятие race condition ===
Стандартный пример, как не нужно использовать multithreading. Пусть есть некоторые общие данные, а два потоки одновременно пытаются выполнить с ними какие-то операции. Например, есть переменная x = 0, два потока пытаются увеличить ее на 1. В итоге может получится получиться как 1, так и 2 (так и вообще непонятно что, см. [http://en.wikipedia.org/wiki/Race_condition]). Вывод: нужно lock'ать данные перед тем, как их использовать.  
=== atomic operations ===
В 11х плюсах, чтобы не получались "race condition" есть atomic operations библиотека. Например, можно писать такой код:
http://en.wikipedia.org/wiki/Asynchronous_I/O#Select.28.2Fpoll.29_loops
http://en.wikipedia.org/wiki/IOCP
 
poll — даём список дескрипторов, из которых хотим читать/писать, он ждёт, пока какой-то будет доступен, и возвращает номер. Также можно по маске.
 
select — как я понимаю, он ещё хуже, даём n, он просматривает дескрипторы <= n
 
epoll — улучшение poll, мы можем заранее делать в него add, он хранит очередь из доступных дескрипторов, поэтому побыстрее (видимо, O(1))
 
kqueue — эквивалент epoll, только FreeBSD и ещё где-то
 
IOCP — это в Windows, тоже использует очередь
== remote procedure call ==
=== зачем это нужно ===
общаться между процессами, и даже вызывать с одного компа процессы на другом компе
 
=== apartment threading model ===
http://www.rsdn.ru/article/com/apartmnt.xml
http://www.introligator.org/articles/3/84 - понятнее
=== reentrancy ===
ну в free threaded сам заботься, а apartment сам все сделает
 
=== достоинства/недостатки apartment threading model ===
Главным достоинством апартамента STA является то, что разработка объекта COM и клиентской части проста в том смысле, что нет нужды заботиться о синхронизации вызовов методов и их выполнения: следующий метод начнет выполняться только после того, как закончится выполнение предыдущего. Аналогично не нужно заботиться о синхронизации доступа к данным объекта.
 
Главным недостатком апартамента STA является его неэффективность. Даже если синхронизация вызовов методов и не нужна, она все равно выполняется.
 
=== free threaded threading model ===
http://www.rsdn.ru/article/com/apartmnt.xml
http://www.introligator.org/articles/3/84 - понятнее(тоже самое)
 
=== достоинства/недостатки free threaded threading model ===
Основным достоинством MTA апартамента является потенциально высокая производительность сервера, вследствие чего он более доступен для клиентов. Вместе с тем разработка объектов такого сервера намного сложнее, так как требуется синхронизировать не только вызовы методов, но и обращение к локальным данным объектов.
 
=== пару слов про реализации (COM, CORBA, D-Bus) ===
== fibers ==
это просто реализация концепции сопрограмм
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682661(v=vs.85).aspx
 
http://ru.wikipedia.org/wiki/%D0%A1%D0%BE%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0 - короче это просто реализация этого принципа. Была нить ее разхреначили на волокна и идут сначала по одному - потом переключились на другой, поделали чето там, вернулись и продолжили идти по первому, например.
=== зачем это нужно ===
Фиберы — это мануально переключаемые потоки. Всегда, когда удобнее вместо синхронизации использовать ручное переключение, применяются фиберы. Также, если потоков много и они однотипны, то целесообразно создавать фиберы, ибо они значительно экономят ресурсы.
 
Можно устроить линейный обход по двоичному дереву поиска. Можно использовать генераторы. Например, генерировать простые числа.
 
=== coroutines ===
http://www.crystalclearsoftware.com/soc/coroutine/
=== generators ===
Подпрограмма возвращает значение только однажды, возврат нескольких значений требует использовать в качестве возвращаемого значения коллекции. Если в некоторых языках это приемлемо, например Forth и Перл, то другие языки, например Си, поддерживают только одно возвращаемое значение, и поэтому необходимо возвращать ссылку на коллекцию. В противовес, сопрограмма может возвращать результат несколько раз, возвращение множества значений требует только вызова сопрограммы несколько раз. Сопрограммы, которые возвращают множество значений, часто называют генераторами.
 
=== как это работает ===
возвращение множества значений требует только вызова сопрограммы несколько раз.
 
=== FLS (fiber local storage) ===
у каждого фибера есть ствой локал сторадж
ФИБЕР МОГУТ ВЫПОЛНЯТЬ РАЗНЫЕ ПОТОКИ
== С++11 ==
=== см. http://gcc.gnu.org/projects/cxx0x.html и http://www.stroustrup.com/C++11FAQ.html ===
 
RUS:http://sergeyteplyakov.blogspot.ru/2012/05/c-11-faq.html#auto // круто //лол кто-то не знал про auto?
=== про каждую фичу надо говорить, зачем это нужно, как это работает ===
=== static_if ===
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3329.pdf
template <unsigned long n>
struct factorial {
static if (n <= 1) {
enum : unsigned long { value = 1 };
} else {
enum : unsigned long {
value = factorial<n - 1>::value * n
};
}
Можно так же смотреть 64 битный ли у нас компилятор. Эти примеры вроде есть в пдфке.
=== modules ===
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3347.pdf
 
Профит от этого будет, например, в улучшении времени компиляции программ и в более понятных ошибках.
=== concepts ===
Это описание свойств типа, необходимых для работы в шаблоне. Компилятор на основе этих данных может производить дополнительные оптимизации, а программист может указывать, что ему нужно от типа, который дают шаблону. В сущности, это нововведение лишь даёт мизерный прирост к скорости и делает более понятными некоторые сообщения компилятора об ошибках.
 
auto concept LessThanComparable<typename T> {
requires SomeConcept<T>;
bool operator<(T, T);
}
 
* Ключевое слово auto указывает, что проверять на совместимость с концептом надо любые типы. Всё, что подошло по условию, концептом поддерживается.
* concept - ключевое слово "это концепт". С уважением, капитан Очевидность.
* LessThanComparable - собственно, название концепта, а в угловых скобках - аналогично объявлению шаблона, удовлетворяющие ему типы. Далее в фигурных скобках идёт описание концепта.
* requires - ключевое слово, которое можно применить и при объявлении шаблона - требует выполнения типом T этого концепта другого концепта SomeConcept. Именно типом T, поскольку их может быть несколько.
* Объявление функции - обязывает претендента на совместимость с концептом такую функцию иметь в ближайшем доступе - будь то где-то снаружи или внутри класса.
 
Применить его можно так:
 
template<LessThanComparable T>
const T& min(const T &x, const T &y) {
return (y < x) ? y : x;
}
 
Или так:
 
template<typename T> requires LessThanComparable<T>
const T& min(const T &x, const T &y) {
return (y < x) ? y : x;
}
 
Последний способ лучше тем, что позволяет указать для типа несколько требований одновременно без необходимости создавать новый концепт, содержащий их все. К слову, концепты можно и наследовать, хотя это и аналогично применению requires.
 
Концепты были убраны из чернового стандарта C++11 в июле 2009 года. Однако опенсорс подхватил идею и реализовал её в ConceptGCC, форке GNU C++ compiler.
 
Остальное можете почитать здесь: http://en.wikipedia.org/wiki/Concepts_(C%2B%2B)
== ranges ==
http://www.boost.org/doc/libs/1_52_0/libs/range/doc/html/index.html-- а может это и не оно, хз [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3350.html#classstd_1_1range] — думаю, все же это. [https://github.com/ericniebler/range-v3] - рабочий прототип, на основе которого пишется [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4569.pdf Ranges TS]
=== зачем это нужно ===
Наверное, чтобы было удобно писать всякие обобщенные алгоритмы. Ranges позволяют взять какую-то часть содержимого произвольного контейнера и применять к ней какие-то операции с одинаковым интерфейсом.
=== как это работает ===
 
== encodings ==
[http://www.unicode.org/faq/utf_bom.html ясно и понятно]
=== понятие code unit, понятие code point, combining characters ===
Code unit — минимальная(по длине) битовая комбинация, которая может представлять символ. Для UTF-8 code unit равен 8, символы могут представляться одним или несколькими 8-битными последовательностями. В UTF-16 и UTF-32 code unit по 16 и 32 бита соответственно. [http://www.coderanch.com/t/416952/java/java/Unicode-code-unit-Unicode-code]
 
Code point — любое значение, которое может представлять символ юникода(0x0–0x10FFFF) [http://www.unicode.org/glossary/#code_point]
 
Combining characters — символы, которые в комбинации с другими дают новые символы (всякие крышечки, точечки, ударения, которые можно нарисовать над буквами).
 
=== UTF-8, overlong sequence ===
Смотрим, как преставляются символы в UTF-8: [http://en.wikipedia.org/wiki/UTF-8#Description]
 
Очевидно, что один и тот же символ может представляться разными последовательностями байт. Но по стандарту представление должно использовать минимальное число байт. Все остальные преставления называются overlong sequences.
 
Утверждают, что это даже бывает полезно. Например, в Modified UTF-8 символ NUL(U+0000) представляют двумя байтами C0 80, чтобы оставить 00 под символ конца строки. <del>Так делает Java для сериализации объектов, добавления строковых констант в .class-файлы и JNI.</del>
 
=== UTF-16, surrogate pair ===
В UTF-16 можно закодировать символы от 0 до 0xD7FF и от 0xE000 до 0x10FFFF, причем 4-байтные символы представляются как есть, а более длинные — с помощью суррогатных пар, для которых и вырезан диапазон 0xD800–0xDFFF.
 
В суррогатных парах старшие 10 бит значения идут в лидирующее (первое) слово, а младшие 10 бит — в последующее (второе). При этом в обоих словах старшие 6 бит используются для обозначения суррогата. Биты с 11 по 15 имеют значения 11011, а десятый бит содержит 0 у лидирующего слова и 1 — у последующего.
 
=== UTF-32 ===
UTF-32 использует ровно 4 байта на каждый символ. Это хорошо, потому что очень просто, и очень плохо, потому что неэффективно по памяти.
=== byte order mark ===
=== endianness, UTF-16BE, UTF-16LE, UTF-32BE, UTF-32LE ===
Два байта, входящие в code unit, при записи можно размещать по-разному. x86 использует little-endian(младшие сначала), а SPARC, ARM и другие — big endian. Чтобы различать их, в начало текста записывают byte order mark(BOM) — U+FEFF. Если считалось FFFE, то порядок little-endian, если FEFF — big. Дополнительный профит BOM — возможность отличить UTF-8 от UTF-16, потому что в UTF-8 FE и FF не используются, а BOM выглядит как EF BB BF(но ни на что не влияет, а просто является меткой). Также можно явно указывать порядок байт в кодировке(UTF-??BE или UTF-??LE), тогда BOM становится не нужен.
Анонимный участник

Навигация