Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
LectionSTL3.doc
Скачиваний:
1
Добавлен:
12.11.2019
Размер:
367.62 Кб
Скачать

VectorA.Push_back(inventory());

if(vectorA.capacity()!=cap)

{

fout << "i= " << i << ", new size " << vectorA.size()

<< ", new capacity " << vectorA.capacity() << std::endl;

}

}

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

i= 0, new size 1, new capacity 1

i= 1, new size 2, new capacity 2

i= 2, new size 3, new capacity 3

i= 3, new size 4, new capacity 4

i= 4, new size 5, new capacity 6

i= 6, new size 7, new capacity 9

i= 9, new size 10, new capacity 13

i= 13, new size 14, new capacity 19

i= 19, new size 20, new capacity 28

i= 28, new size 29, new capacity 42

i= 42, new size 43, new capacity 63

Видно, что при вставке пятидесяти элементов перераспределение памяти происходит 11 раз. Теперь рассмотрим другой код:

std::ofstream fout("test1.dat");

if(fout.is_open()!=true)

{

std::cout << "Can't open file!!" << std::endl;

return 1;

}

int n=50;

std::vector<inventory> vectorA;

VectorA.Reserve(n);

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

{

std::vector<inventory>::size_type cap=vectorA.capacity();

VectorA.Push_back(inventory());

if(vectorA.capacity()!=cap)

{

fout << "i= " << i << ", new size " << vectorA.size()

<< ", new capacity " << vectorA.capacity() << std::endl;

}

}

При выполнении данного кода вывода в файл не происходит, поскольку функция reserve() резервирует память сразу для пятидесяти элементов и при вставке перераспределения памяти не происходит. Это гарантирует, что вставка в конец вектора не портит никакие итераторы и ссылки. Вставки в средину делают недействительными только те итераторы и ссылки, которые указывают на точку вставки или после нее. Если имеется некоторая часть программы, в которой требуется поддержка нескольких итераторов, указывающих в различные места вектора, следует вызвать reserve с достаточно большим параметром во избежание перераспределения памяти во время выполнения этой части.

Следует отдельно сказать о классе vector, который специализирован для значений bool. Контейнер vector<bool> хранит значения true и false в виде отдельного бита. С точки зрения функциональности эта специализация идентична другим векторам с дополнением метода void flip(), который обращает все биты в векторе.

Приведем примеры использования контейнера vector.

Задача. Дано произвольное большое целое положительное число N. Найти его разложение на простые множители.

Мы не знаем заранее, сколько простых множителей будет содержать исходное число, поэтому мы будем использовать vector для того, чтобы можно было эффективно добавлять данные в конец контейнера. Создадим функциональный объект, который принимает целое число и возвращает количество простых множителей. В качестве поля объект содержит вектор.

class Factor:public std::unary_function<unsigned int, std::vector<unsigned int>::size_type>

{

private:

std::vector<unsigned int> *vec;

public:

Factor();

Factor(std::vector<unsigned int>::size_type x);

Factor(const Factor &a);

Factor& operator=(const Factor &a);

~Factor();

std::vector<unsigned int>::size_type operator()(unsigned int N);

std::vector<unsigned int> getfactor()const;

};

Его методы определены так:

Factor::Factor()

{

this->vec = new std::vector<unsigned int>();

}

Factor::Factor(std::vector<unsigned int>::size_type x)

{

this->vec = new std::vector<unsigned int>();

this->vec->reserve(x);

}

Factor::Factor(const Factor &a)

{

this->vec = new std::vector<unsigned int>(*(a.vec));

}

Factor& Factor::operator=(const Factor &a)

{

if(this==&a)

{

return *this;

}

else

{

this->vec->assign(a.vec->begin(),a.vec->end());

return *this;

}

}

Factor::~Factor()

{

this->vec->clear();

delete this->vec;

}

std::vector<unsigned int>::size_type Factor::operator()(unsigned int N)

{

unsigned int d=2;

while(N>1)

{

while(N%d==0)

{

this->vec->push_back(d);

N/=d;

}

++d;

}

return this->vec->size();

}

std::vector<unsigned int> Factor::getfactor()const

{

return std::vector<unsigned int>(*(this->vec));

}

И главная программа:

Factor F;

std::vector<unsigned int>::size_type s = F(N);

std::vector<unsigned int> temp = F.getfactor();

std::cout << s << std::endl;

for(std::vector<unsigned int>::const_iterator itr=temp.begin(); itr!=temp.end(); ++itr)

{

fout << *itr << " ";

}

Существует и другой пример использования контейнера vector. Это знаменитая задача о нахождении всех простых чисел в интервале от 2 до N.

Решето Эратосфена.

class Eratosthenes:public std::unary_function<unsigned int, std::vector<unsigned int> >

{

public:

std::vector<unsigned int> operator()(unsigned int N);

};

std::vector<unsigned int> Eratosthenes::operator()(unsigned int N)

{

std::vector<unsigned int> result;

std::vector<bool> temp(N+1,false);

for(unsigned int i=2;i<=N;++i)

{

if(temp.at(i)==false) //находим нулевые элементы

{

temp.at(i)=true; // присваиваем им значение 1

result.push_back(i); // помещаем их в список

for(unsigned int d=2*i;d<=N;d+=i)

{

// присваиваем 1 всем множителям числа i

temp.at(d)=true;

}

}

}

return result;

}

Приложение: Методы класса inventory:

int inventory::count=0;

inventory::inventory():cost(0),quantity(0)

{

inventory::count++;

std::strcpy(this->item, "Nothing");

std::cout << "Default constructor " << inventory::getcount() << std::endl;

}

inventory::inventory(const char *name, double c, int q):cost(c),quantity(q)

{

inventory::count++;

std::strcpy(this->item, name);

std::cout << "Constructor " << getcount() << std::endl;

}

inventory::inventory(const inventory &src):cost(src.cost),quantity(src.quantity)

{

inventory::count++;

std::strcpy(this->item, src.item);

std::cout << "Copy constructor " << inventory::getcount() << std::endl;

}

inventory::~inventory()

{

inventory::count--;

std::cout << "Destructor " << inventory::getcount() << std::endl;

}

int inventory::getcount()

{

return inventory::count;

}

inventory & inventory::operator=(const inventory &rhs)

{

if(this==&rhs)

{

return *this;

}

else

{

std::strcpy(this->item, rhs.item);

this->cost=rhs.cost;

this->quantity=rhs.quantity;

return *this;

}

}

bool operator==(const inventory &a1, const inventory &a2)

{

if((std::strcmp(a1.item,a2.item)==0)&&(a1.cost==a2.cost)&&(a1.quantity==a2.quantity))

{

return true;

}

else

{

return false;

}

}

std::ostream & operator <<(std::ostream &stream, const inventory &obj)

{

stream << obj.item << ' ' << obj.cost << ' ' << obj.quantity << std::endl;

return stream;

}

std::istream & operator >> (std::istream &stream, inventory &obj)

{

std::cout << "Enter item, cost and quantity:" << std::endl;

stream.getline(obj.item, 12, ' ');

stream >> obj.cost >> obj.quantity;

return stream;

}

12

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]