![]() Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
String s;
Int i; while(cin> > s> > i) vp.emplace_back(s, i);
Очевидно, что контейнеры – это не единственное место стандартной библиотеки, которое пользуется преимуществами новых языковых возможностей. Так, например:
Аллокаторы с дополнительным состоянием Для простоты и компактности контейнеров С++98 не требует от них поддержки аллокаторов с состоянием. Аллокаторы не должны были хранится в объектах контейнеров. Такое поведение все еще используется по умолчанию в С++11, но появилась возможность использования аллокаторов с состоянием, например, можно использовать аллокатор, содержащий указатель на область памяти из которой происходит выделение. Например: // Вариант для C++98не содержит данных template< class T> class Simple_alloc { // обычная реализация аллокатора }; class Arena { void* p; Int s; public: Arena(void* pp, int ss); // выделяет из диапазона p[0..ss-1] }; template< class T> struct My_alloc { Arena& a; My_alloc(Arena& aa): a(aa) { } // обычная реализация аллокатора }; Arena my_arena1(new char[100000], 100000); Arena my_arena2(new char[1000000], 1000000); // память выделяется аллокатором по умолчанию vector< int> v0; // выделяет из my_arena1 vector< int, My_alloc< int> > v1(My_alloc< int> {my_arena1}); // выделяет из my_arena2 vector< int, My_alloc< int> > v2(My_alloc< int> {my_arena2}); // выделяет с помощью Simple_alloc vector< int, Simple_alloc< int> > v3;
Обычно, для облегчения синтаксиса используют typedef. Нет никакой гарантии того, что Simple_alloc и аллокатор, используемый по умолчанию столкнутся с нехваткой памяти, но это можно гарантировать с помощью небольшого количества метапрограммирования шаблонов. Таким образом, использование аллокатора приводит к дополнительному расходу памяти только в том случае, когда аллокатор обладает состоянием (как My_alloc). При использовании пользовательских аллокаторов с контейнерами может возникнуть одна коварная проблема: должен ли элемент располагаться в той же самой выделенной области, что и контейнер? Например, если вы используете Your_allocator для Your_string для выделения его элементов, и я использую My_allocator для выделения элементов в объекте My_vector, тогда какой аллокатор должен использоваться для элементов в типе My_vector< Your_allocator> >? Решение заключается в возможности указать контейнеру какой аллокатор должен передаваться его элементам. Например, предположим, что у меня есть аллокатор My_alloc и я хочу, чтобы vector< string> использовал My_alloc дляэлементов вектора и для выделения элементов строки. Прежде всего, нужно создать версию строки с My_alloc. // строка с нужным аллокатором using xstring = basic_string< char, char_traits< char>, My_alloc< char> >;
Затем, мне нужно создать версию vector, принимающую строки и My_alloc, и передающий этот аллокатор строке: using svec = vector< xstring, scoped_allocator_adaptor< My_alloc< xstring> > >;
Теперь мы можем создать аллокатор типа My_alloc< xstring>: svec v(svec:: allocator_type(My_alloc< xstring> {my_arena1}));
Теперь svec – это вектор строк, который использует My_alloc для выделения памяти для своих элементов. Новое поведение заключается в использовании «адаптера» (“wrapper”) из стандартной библиотеки под названием scoped_allocator_adaptor, который указывает на то, что строки также должны использовать My_alloc. Обратите внимание, что адаптер может (очень легко) преобразовывать My_alloc< xstring>, требуемый типу xstring. Так что у нас есть 4 варианта: // vector и string используют свой собственный // аллокатор (аллокатор по умолчанию): using svec0 = vector< string>;
|