C++

О блоге

Рейтинг
6.11
голосов: 4
Практика программирования на C++. Методы, советы, секреты…

Администраторы (1)

Модераторы (0)

Модераторов здесь не замечено

Читатели (1)

C++

Эффективный код на С++

Вторая статья по оптимизации кода на С++. Первую можно найти тут. В статье рассмотрены некоторые рекомендации, позволяющие сделать ваш код более эффективным.

1. Минимизируйте количество локальных переменных. Тогда компилятор сможет их хранить в регистрах, а не на стеке.

2. Объявляйте переменные там, где они будут использоваться, давая им наименьшую область видимости. Это способствует выполнению пункта 1.

void  Compute( conat char* name )
{
   if( !name )
   {
      A a; // переменная будет жить до конца условия, но не до конца функции
      ...
   }
}

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


Читать дальше
C++

Что такое TLS и как ее использовать?

Уже давно программы перестали быть однопоточными. Сейчас даже маленькие приложения используют множество потоков, для различных фоновых процессов. Для разработки эффективного и thread-save кода нужно понимание того, что такое TLS (Thread Local Storage — локальная память потока) и того когда и как этим пользоваться.

Зачем нужна TLS


Допустим создается приложение которое параллельно обрабатывает большой набора данных. Существует некий массив, каждый элемент которого вместе с его содержимым соответствует отдельному потоку, который ответственен за вычисления связанные с этим элементом. Откуда конкретный поток узнает, какой индекс в глобальном массиве его?

Можно передать функции потока ThreadProc этот индекс в качестве параметра. Тогда индекс будет храниться в локальной переменной потока. Но представьте, что ThreadProc вызывает какую-то функцию. Потом еще одну, и так он может вызывать сотни функций с разными уровнями вложенности. Куда денется индекс, которым владеет поток? Можно попытаться передавать этот индекс каждой функции, но это очевидно будет сказываться на эффективности. Именно для решения подобных проблем нужна память, специфичной для потока — TLS.




Читать дальше
C++

Методы оптимизации памяти (Memory optimization)

1. Минимизируйте количество выделений памяти


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

Во вторых, при постоянном выделение-освобождение памяти идет ее фрагментация. Если в системе ограниченный объем памяти, то наступит момент, когда не удастся выделить новый кусок связной памяти. Причем у вас может быть свободно 50 мегабайт, а выделить не удастся даже 10.

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


Читать дальше
C++

Использование Precompiled файла, для ускорения компиляции

Реальные приложения могут иметь множество проектов в одном салюшине в Visual Studio. Эти проекты могут содержать сотни файлов исходного кода и это несомненно скажется на времени компиляции. Существует способ значительно ускорить компиляцию создав Precompiled файл.

Представьте, что у вас есть множество классов, каждый из которых имеет свои .h и .cpp файлы. При этом если несколько классов подключают один и тот же, то он будет компилироваться множество раз. Идея Precompiled файлов заключается в том, чтобы компилировать наиболее часто используемые модули всего один раз. Это значительно ускоряет процесс компиляции программы.


Читать дальше
C++

Вычисление суммы элементов массива с сохранением точности

На сайте вакансий Яндекса предлагают вычислить сумму элементов массива и предлагают три варианта решения задачи. Их можно посмотреть тут. Эти примеры намеренно не оптимальны и существует лучшее решение задачи. Рассмотрим сначала предлагаемый вариант решения:


double sum1(std::vector<double>& v)
{    
    if (v.empty()) {
        return 0.0;
    }
    for(size_t i = 0; i < v.size() - 1; ++i) {
        std::sort(v.begin()+i, v.end());
        v[i+1] += v[i];
    }
    return v.back();
}


Сразу бросается в глаза сортировка при суммировании следующего элемента. Это требуется чтобы суммировались сначала меньшие числа. Точности double не хватает для данных вычислений, поэтому если поступить иначе и складывать числа от больших к меньшим, то при добавлении маленьких чисел они могут быть денормализованы с огромной ошибкой.


Читать дальше
C++

Определение размера массива

Как обычно в С++ определяют размер массива, а очень просто, используют следующую конструкцию:


#define count_of( arg ) ( sizeof( arg ) / sizeof( arg[ 0 ] ) )


Однако она может стать причиной ошибки, если подсунуть туда указатель, не являющийся массивом, например, указатель на функцию. Проблему можно решить следующим образом (взято из исходных кодов проекта Chromium — основы браузера Google Chrome):


template <typename T, size_t N>
char (&ArraySizeHelper(T (&array)[N]))[N];
#define arraysize(array) (sizeof(ArraySizeHelper(array)))


Проблема решается потому, что массив передается по ссылке, а не по указателю.
C++

Кроссплатформенное программирование. Организация кода

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

Разумеется можно не обращать внимание на то, что программа делается под разные платформы и вставлять платформо-зависимый код во все участки программы, где это потребуется. Однако это очень быстро превратит код в нечитабельную свалку. Портировать его под новую платформу будет крайне сложно.

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


Читать дальше
C++

Кроссплатформенное программирование. Низкоуровневые средства

Сегодня существует огромное количество различных платформ, под которые можно разрабатывать программное обеспечение. Однако не хочется писать программу индивидуально под каждую платформу. Значительно лучше организовать код таким образом, чтобы большая часть функционала была абстрагирована от платформо-зависимого кода.

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

Другая часть кода будет представлять собой обертку над платформо-зависимым функционалом. И именно об способах организации кода для этой обертки и пойдет речь в данной статье.


Читать дальше
C++

Глобальная обработка исключений в С++

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


Читать дальше
C++

Placement new, или как создать объект в выделенной памяти

Как понятно из названия, в данной статье речь пойдет о том, как создать объект в выделенной памяти и зачем это может быть необходимо.

Работа с памятью через оператор new может быть крайне не желательна в больших системах. Особенно на платформах, где ограниченный размер памяти, например при написание консольных игр. Выделение памяти в куче приводит к ее фрагментации, и через определенное время может не оказаться достаточного свободного блока памяти под новое выделение, что приведет к падению приложения.

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

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


Читать дальше

Warning: Unknown: write failed: No space left on device (28) in Unknown on line 0

Warning: Unknown: Failed to write session data (files). Please verify that the current setting of session.save_path is correct (/var/lib/php5) in Unknown on line 0