nyaload

Журнал Пушыстого

Журнал Пушыстого

Entries by tag: c++

π++
nyaload
_winnie
в С++ нет числа π в стандартной библиотеке. M_PI/_USE_MATH_DEFINES зачем-то сломали в g++ при использовании -std=c++11, а взамен ничего не предложили.

http://stackoverflow.com/questions/1727881/how-to-use-the-pi-constant-in-c

В результате проще в каждом cpp файле копипастить строчку «const double pi = 3.14159265358979323846;» (или «constexpr auto pi = 3.14159265358979323846» в c++11, или acos(-1) вместо константы).

--------------
PS. этот пост дубликат предыдущего, предыдущий я удалил из-за этого бага. Уже оставленные чужие коментарии достал из почты, скопирую в комментарии.
Tags:

Неявно квадратичный алгоритм
nyaload
_winnie
vector<int> v;
for (int i = 0; i < 1000*1000; ++i) {
    v.reserve(v.size() + 10);
    v.push_back(i);
}

Если удалить строчку с reserve, то отрабатывает за долю секунды, с reserve - зависает на 5 минут.
Tags:

shared_ptr
nyaload
_winnie
У std::(boost::)shared_ptr в блоке, который хранит счетчик, есть ещё указатель на функцию удаления (deleter), который запоминается в момент создания shared_ptr
Это позволяет:
* не париться с виртуальным деструктором, если мы кастуем shared_ptr<derived> в shared_ptr<base> (not recommended, если shared_ptr это не единственный указатель в проекте).
* не париться с переносом деструктора из .h в .cpp, когда делаем PImpl
* передавать shared_ptr в другой модуль, у которого свой собственный аллокатор памяти и свой delete
* Вообще не привязывать способ удаления к типу в shared_ptr (можно использовать свой кастомный аллокатор, и пользователям shared_ptr<T> не нужно знать, какой аллокатор использовался при создании T).

Так же у shared_ptr есть отдельный счетчик для weak-ссылок (иногда нужно в многопоточном программировании и прочих случаях "мы не можем статически отследить вложенность lifetime").

Функция make_shared позволяет не делать две аллокации на счетчик и объект, объединяя их в один кусок памяти.
Tags:

Friendly Dialect of C
nyaload
_winnie
Если компилятор работает в предположении что люди ошибок не делают, то компилятор считает что true=false. Если компилятор считает, что программист нигде не ошибся, значит в компиляторе (в авторе компилятора) баг.

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

Голос разума, давайте компилятор будет жить в реальности. А не в вымышленном мире, где теоретически может сущестовать программа в миллион строк, не содержащая ни одной ошибки: Proposal for a Friendly Dialect of C - http://blog.regehr.org/archives/1180

==========================================
Пояснение, почему компиляторы так хотят верить в идеальность программистов:
http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html

И следущие части этого рассказа, в которых описано в том числе и "как с этим бороться":
http://blog.llvm.org/2011/05/what-every-c-programmer-should-know_14.html
http://blog.llvm.org/2011/05/what-every-c-programmer-should-know_21.html
Tags:

ударение в +ы
nyaload
_winnie
«плюсы́» - C++
«плю́сы» - что-то хорошее.
Tags:

3 решения
nyaload
_winnie
По сети гуляет вот такая программистская задача: http://dobrokot.ru/pics/i2014-09-30__12-57-29_75kb.jpg
Она простенькая, хотя бы одно решение вы придумаете очень быстро.

Написал для неё брутфорсер ( https://gist.github.com/dobrokot/47f4bd6e1ecb4a9157eb ) , решений действительно только 3.

В ходе брутфорса было сгенерировано 13000 исходников, из которых скомпилировалось 794 бинарника. 1 программа зависла, эта та, в которой printf("-") заменился на dprintf("-"). Точнее, не зависла, а попыталась сделать очень много системных вызовов на некорректном дескрипторе.

Read more...Collapse )

(спасибо mehas@ с closedcircles за ссылку )
Tags:

GetKey() { return tie(this->x, this->y, this->z); }
nyaload
_winnie
Предположим, мы программируем на крестах++. Предположим, что у нас есть структура из трёх полей. Мы захотели их посортировать, ну или там сохранить в std::map(aka чёрно-красное дерево), и тп.
Вместо того, чтобы выписывать аккуратно в столбик лексиграфическое сравнение трёх полей - можно завести функцию GetKey(), которая возращает tuple ( или pair<x, pair<y, z> > ) со ссылками/копиями полей. Или вообще ((x * MAX_Y + y) *MAX_Z + z):uint32_t.

Теперь operator< реализуется как (this->GetKey() < rhs.GetKey()). И скорее всего не нужно заводить компаратор для std::map, можно просто myMap[x.GetKey()]

От программирования к математике: если у нас есть операция порядка (strict weak order), то существует функция GetKey, как факторизация по отношению эквивалентности !(x<y)&&!(y<x)
Tags:

warning: class member declared, but not used.
nyaload
_winnie
Написал простейшую регулярку ( '^ *[a-zA-Z0-9_]+ +[a-zA-Z0-9_]+;$' ), выцепляющую члены классов. Без шаблонов, и прочих заморочек, она цепляет кучу лишнего. Можно её апгрейдить или вообще переходить к AST, но даже так - работает.


Если член C++ класса упоминается в коде не больше двух раз - то в 50% случаев это означает какой-то ахтунг (переменную или забыли инициализировать, или забыли использовать).

Почему именно константа 2?

Потому что типично переменная без инициализатора в объявлении должна встретиться в коде три раза:
1) при декларации
2) при чтении из неё
3) при записи в неё.

Если переменная встретилась только два раза - это значит её или не инициализировали чем-то осмысленным, или не использовали.

Ложных срабатываний - около половины (типично через временную ссылку на этот же объект), но вторая половина - справедливо указало на ненужность члена данных или на опечатку.

upd: собственно, скрипт: https://gist.github.com/dobrokot/82ade3a1c399573922b8
Tags:

Почему std::accumulate - не жилец
nyaload
_winnie
Потому что многобукв. Цикл - написать проще, чем вызывать std::accumulate с нужными параметрами. Как в C++11, так и до. Пусть нам надо просуммировать x.field типа float, где x из контейнера vec. float суммировать будем в double, во избежание потери точности.

//обычное суммирование:
double s = 0; for (auto &x: vec) { s += x.field; }; return s;

//суммирование через std::accumulate - длиннее в два раза
return std::accumulate(vec.begin(), vec.end(), double(0), [](double s, const TElem &x) { return s + x.field; });

//при попытке использовать сомнительные или недоступные пока сокращения - всё равно длиннее:
return Sum(vec, [](double s, auto &x) {return s+x.field;}, 0.0);

//если бы не странные ограничения С/C++:
return Sum(vec, ((s, x) -> s + x.field), double(0));
Tags:

Особенности реализации #pragma once в gcc
nyaload
_winnie
Это исследование с gcc написал Vladimir Kozbin ( https://twitter.com/wawakadesu ), я его сюда только лишь скопировал.
--------------------------------------------------
Задачка.

Возьмём файлик a.h

#pragma once
x += 1;

Read more...Collapse )
Tags:

?

Log in