Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
for
мне кажется неуместным. Он хорош, когда действительно важно бежать с конца в начало, но, поскольку в ваших функциях вам все равно, то лучше использовать классическийfor (size_t i=0; i<Dim; ++i)
Экономить 3 символа это, конечно, хорошо, но в отличие от классического варианта этот при прочтении прямо таки просит взять в руки бумажку и проверить, что тут нигде не налажали. Кроме того, отказ от него позволил бы вам сэкономить целый абзац в статье, раз уж вам это так нравиться.;
на той же строке, что и шапка, писать так:for (size_t i=len; i--; ret[i]=v[i]) {}
или так:for (size_t i=len; i--; ret[i]=v[i])
;
Циклы являются одним из тех мест, где малое повышение эффективности значительно улучшает выполнение программы, потому что их код выполняется многократно. Так как сравнение с нулем обычно более эффективно, чем сравнение с определенным числом, то цикл с уменьшающимся счетчиком, как правило, выполняется быстрее.
/////////////////////////////сумма векторов
template<size_t Dim,typename Number>vec<Dim,Number > operator+(vec<Dim,Number > lhs, const vec<Dim,Number >& rhs)
{
for(size_t i=Dim;i--;)
{
lhs[i]+=rhs[i];
}
return(lhs);
}
Но мы можем заставить компилятор задействовать именно ее, поэтому данный аргумент — слабый.
Здравствуйте.
К сожалению, я не могу писать в комментарии к статьям.
Если вам не сложно, ответье пожалуйста на вопрос к статье
Краткий курс компьютерной графики 3.1
Вы используете обратный цикл, далее в комментарии вы мотивириуете это тем, что проверка на 0 быстрее плюс есть специальная инструкция.
Но разве при обратном проходе у вас не будут кэш мисы?
Я понимаю, что в вашем случае размер памяти очень маленький, и вы попадете в линейку кеша, но вы же сами в комментарии пишете, что это показано для обучающих целей, а не только для этого конкретного варианта.
std::transform(lhs.begin(), lhs.end(), rhs.begin(), lhs.begin(), std::minus<int>());
итератор (который тоже придется писать)Можно простые указатели возвращать, они вполне себе итераторы. Можно даже набыдлокодить и написать как-нибудь так:
std::transform(&lhs[0], &lhs[0] + Dim, &rhs[0], &lhs[0], std::minus<int>())
У него проверка выхода за границы включена всегда по стандарту и все тут
at()
, а в операторе []
никакой проверки нет.[]
зависит от реализации STL. Например, здесь пишут, что реализация STL в Visual Studio 2005 и 2008 делает эту проверку и для at()
и для []
. У него проверка выхода за границы включена всегда по стандарту и все тут.
Читай матчасть!
binary_op must not invalidate any iterators, including the end iterators, or modify any elements of the ranges involved.
// transform algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::transform
#include <vector> // std::vector
#include <functional> // std::plus
int op_increase (int i) { return ++i; }
int main () {
std::vector<int> foo;
std::vector<int> bar;
// set some values:
for (int i=1; i<6; i++)
foo.push_back (i*10); // foo: 10 20 30 40 50
bar.resize(foo.size()); // allocate space
std::transform (foo.begin(), foo.end(), bar.begin(), op_increase);
// bar: 11 21 31 41 51
// std::plus adds together its two arguments:
std::transform (foo.begin(), foo.end(), bar.begin(), foo.begin(), std::plus<int>());
// foo: 21 41 61 81 101
std::cout << "foo contains:";
for (std::vector<int>::iterator it=foo.begin(); it!=foo.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
std::minus<int>()
в нашем случае) не имеет права менять объекты, а не то, что отрезки не могут перекрываться. Объект, собственно, ничего и не меняет, просто вычитает одно число из другого и выдает результат.Remarks:result
may be equal tofirst
in case of unary transform, or tofirst1
orfirst2
in case of binary transform.
result
в стандарте — это предпоследний параметр функции (итератор, по которому пишется ответ).std::transform(V.begin(), V.end() - 1, V.begin() + 1, V.begin(), second_arg);
Целью этих требований является возможность параллельных или неупорядоченных реализаций функции std::transform.
В зависимости от порядка примененияПорядок применения в общем случае фиксирован — с начала в конец. Требование на входные итераторы —
InputIterator
, это такая суровая штука, что когда вы переходите к следующему итератору, все предыдущие могут быть уже невалидны (хороший пример: итератор чтения из файла).Так как сравнение с нулем обычно более эффективно, чем сравнение с определенным числом, то цикл с уменьшающимся счетчиком, как правило, выполняется быстрее.— Этот совет несколько устарел.
Однако стоит также вспомнить, что в x86 действительно есть специальная инструкция loop, которая делает как раз то, что нужно:— А это вообще антиоптимизация. На современных процессорах LOOP очень медленный по сравнению с наивным инкрементом, сравнением и переходом. Пример обсуждения на SO
Появление этого цикла тесно связано с использованием size_t для индексации массивов.
3.1, 3.14 и 3.141Нумерация по знакам числа пи? Или просто так совпало?
а также показать, что эти статьи — отдельная сущность.Каким образом нумерация внутри цикла может показывать, что статьи не из цикла? Ваша статья сейчас называется «Краткий курс компьютерной графики». Про графику ни слова. Ну сделайте отдальный цикл статей.
81.7144592952612 356384634040296077728271484375
81.7144592952612 498493181192316114902496337890
а мы работаем в рамках C++98, как бы печально это не было.
Данная статья написана в тесном сотрудничестве
Краткий курс компьютерной графики: пишем упрощённый OpenGL своими руками, статья 3.1 из 6