#include "kvector.hpp"
#include
#include
#include
using namespace std;
int main() {
kvector
cout << "sum = " << accumulate(v.begin(), v.end(), 0) << endl;
v *= 3;
cout << "sum = " << accumulated.begin(), v.end(), 0) << endl;
v += 1;
cout << "sum = " << accumulate(v.begin(), v.end(), 0) << endl;
}
Программа примера 11.18 выдаст следующий результат.
sum = 10
sum = 30
sum = 34
Представленный в примере 11.17 шаблон kvector
является гибридом valarray
и шаблона массива, предложенного в TR1. Как и valarray
, вектор kvector
представляет собой последовательность значений заданного числового типа, однако подобно массиву TR1::array
его размер известен на этапе компиляции.
Характерной особенностью шаблона kvector
является то, что для его инициализации может использоваться синтаксис, применяемый для массивов, и то, что он имеет функции-члены begin
и end
. Фактически kvector
можно рассматривать как псевдоконтейнер, т.е. он удовлетворяет некоторым, но не всем требованиям концепции стандартного контейнера. Следствие этого — более легкое применение kvector
в стандартных алгоритмах по сравнению с valarray
.
Другое преимущество шаблонного класса kvector
состоит в том, что он поддерживает синтаксис, используемый при инициализации массивов.
int x;
kvector
Этот синтаксис возможен только потому, что kvector
является агрегатом. kvector
его заполнить значениями по умолчанию.
kvector
В результате этот вектор будет заполнен нулями.
Как вы видите, при его реализации мной был найден компромисс между полным удовлетворением требований, предъявляемых к стандартным контейнерам, и возможностью использования синтаксиса, применяемого при инициализации массивов. Аналогичный компромисс был найден при проектировании шаблона array
, удовлетворяющего требованиям TR1.
Возможно, самое большое преимущество kvector
над реализациями динамического вектора проявляется в его высокой производительности. По двум причинам шаблон kvector значительно эффективнее, чем большинство реализаций динамических векторов
: компиляторы очень хорошо справляются с оптимизацией циклов фиксированною размера, и здесь нет динамического распределения памяти. Различия в производительности особенно проявляются при работе с небольшими матрицами (например, 2×2 или 3×3), которые часто встречаются во многих приложениях.
Введенное с помощью typedef имя self
я использую в примере 11.17 и в последующих примерах; оно представляет собой удобное краткое имя, которое я использую для ссылки на тип текущего класса. Программу значительно легче писать и воспринимать при использовании self вместо имени класса.
11.10. Вычисление скалярного произведения
Имеется два контейнера, содержащих числа, причем они имеют одинаковую длину, и требуется вычислить их скалярное произведение.
Пример 11.19 показывает, как можно вычислить скалярное произведение, используя функцию inner_product
из заголовочного файла
.
#include
#include
#include
using namespace std;
int main() {
int v1[] = { 1, 2, 3 };
int v2[] = { 4, 6, 8 };
cout << "the dot product of (1,2,3) and (4,6,8) is ";
cout << inner_product(v1, v1 + 3, v2, 0) << endl;
}
Программа примера 11.19 выдает следующий результат.
the dot product of (1,2,3) and (4,6,8) is 40