Читаем Thinking In C++. Volume 2: Practical Programming полностью

Sometimes you need the behavior or efficiency of one kind of container for one part of your program, and you need a different container’s behavior or efficiency in another part of the program. For example, you may need the efficiency of a deque when adding objects to the container but the efficiency of a vector when indexing them. Each of the basic sequence containers (vector, deque, and list) has a two-iterator constructor (indicating the beginning and ending of the sequence to read from when creating a new object) and an assign( ) member function to read into an existing container, so you can easily move objects from one sequence container to another.

The following example reads objects into a deque and then converts to a vector:

//: C07:DequeConversion.cpp

// Reading into a Deque, converting to a vector

//{-bor}

#include

#include

#include

#include

#include

#include "Noisy.h"

using namespace std;

int main(int argc, char* argv[]) {

  int size = 25;

  if(argc >= 2) size = atoi(argv[1]);

  deque d;

  generate_n(back_inserter(d), size, NoisyGen());

  cout << "\n Converting to a vector(1)" << endl;

  vector v1(d.begin(), d.end());

  cout << "\n Converting to a vector(2)" << endl;

  vector v2;

  v2.reserve(d.size());

  v2.assign(d.begin(), d.end());

  cout << "\n Cleanup" << endl;

} ///:~

You can try various sizes, but note that it makes no difference—the objects are simply copy-constructed into the new vectors. What’s interesting is that v1 does not cause multiple allocations while building the vector, no matter how many elements you use. You might initially think that you must follow the process used for v2 and preallocate the storage to prevent messy reallocations, but this is unnecessary because the constructor used for v1 determines the memory need ahead of time.

<p>Cost of overflowing allocated storage</p>

It’s illuminating to see what happens with a deque when it overflows a block of storage, in contrast with VectorOverflow.cpp:

//: C07:DequeOverflow.cpp

//{-bor}

// A deque is much more efficient than a vector

// when pushing back a lot of elements, since it

// doesn't require copying and destroying.

#include

#include

#include "Noisy.h"

using namespace std;

int main(int argc, char* argv[]) {

  int size = 1000;

  if(argc >= 2) size = atoi(argv[1]);

  deque dn;

  Noisy n;

  for(int i = 0; i < size; i++)

    dn.push_back(n);

  cout << "\n cleaning up \n";

} ///:~

Here you will have relatively few (if any) destructors called before the words "cleaning up" appear. Since the deque allocates all its storage in blocks instead of a contiguous array like vector, it never needs to move existing storage of each of its data blocks. (Thus, no additional copy-constructions and destructions occur.) The deque simply allocates a new block. For the same reason, the deque can just as efficiently add elements to the beginning of the sequence, since if it runs out of storage, it (again) just allocates a new block for the beginning. (The index block that holds the data blocks together may need to be reallocated, however.) Insertions in the middle of a deque, however, could be even messier than for vector (but not as costly).

Because of deque’s clever storage management, an existing iterator is not invalidated after you add new things to either end of a deque, as it was demonstrated to do with vector (in VectorCoreDump.cpp). If you stick to what deque is best at—insertions and removals from either end, reasonably rapid traversals and fairly fast random-access using operator[ ]—you’ll be in good shape.

<p>Checked random-access</p>

Both vector and deque provide two ways to perform random access of their elements: the operator[ ], which you’ve seen already, and at( ), which checks the boundaries of the container that’s being indexed and throws an exception if you go out of bounds. It does cost more to use at( ):

//: C07:IndexingVsAt.cpp

// Comparing "at()" to operator[]

#include

#include

#include

#include

#include "../require.h"

using namespace std;

int main(int argc, char* argv[]) {

  long count = 1000;

  int sz = 1000;

  if(argc >= 2) count = atoi(argv[1]);

  if(argc >= 3) sz = atoi(argv[2]);

  vector vi(sz);

  clock_t ticks = clock();

  for(int i1 = 0; i1 < count; i1++)

    for(int j = 0; j < sz; j++)

      vi[j];

  cout << "vector[] " << clock() - ticks << endl;

  ticks = clock();

  for(int i2 = 0; i2 < count; i2++)

    for(int j = 0; j < sz; j++)

      vi.at(j);

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных