#include <iostream>
#include <memory>
#include <vector>
#include <string>
#include <algorithm>
#include <iterator>
static int default_constructed = 0;
static int constructed = 0;
static int copied = 0;
static int moved = 0;
static int destroyed = 0;
struct Foo
{
std::string attr1;
std::vector<int> attr2;
Foo() : attr1(), attr2() { ++default_constructed; }
Foo(const std::string &str,
const std::vector<int> &v) :
attr1(str), attr2(v) { ++constructed; }
Foo(Foo &&x) :
attr1( std::move(x.attr1) ),
attr2( std::move(x.attr2) ) { ++moved; }
Foo(const Foo &x) : Foo(x.attr1, x.attr2) { ++copied; }
~Foo() { ++destroyed; }
};
int main()
{
std::allocator<Foo> alloc;
// выделим место под 100 объектов Foo
Foo *array100 = alloc.allocate(100);
// запишем кол-во
size_t size = 100;
// и сконструируем столько же
std::uninitialized_fill( array100,
array100 + size,
Foo("string", {1000, 42}) ); // constructed = 1 (ref)
// copy constructed = 100
// destroyed = 1
// увеличим место - 1000
Foo *array1000 = alloc.allocate(1000);
size_t new_size = 1000;
// объекты array100 нужно переместить в новое место
// если тип обладает перемещающим конструктором, то будет использован именно он
std::uninitialized_copy( std::make_move_iterator(array100),
std::make_move_iterator(array100 + size),
array1000 ); // move constructed = 100
// инициализируем остальные 900 элементов
std::uninitialized_fill( array1000 + size,
array1000 + new_size,
Foo("string v2", {1000, 87}) ); // constructed = 1 (ref)
// copy constructed = 900
// destroyed = 1
// объекты array100 больше не валидны
std::for_each(array100, array100 + size, [&alloc](Foo &x) { x.~Foo(); } );
// destroyed = 100
// освободим место под array100
alloc.deallocate(array100, size);
array100 = nullptr;
// обновим размер
size = new_size;
// array1000 больше не нужен
// уничтожим объекты
std::for_each(array1000, array1000 + size, [&alloc](Foo &x) { x.~Foo(); } );
//destroyed = 1000
// освободим память
alloc.deallocate(array1000, size);
// перестраховка
array1000 = nullptr;
std::cout << "Objects default constructed = " << default_constructed
<< "\nObjects constructed = " << constructed
<< "\nObjects copy constructed = " << copied
<< "\nObjects move constructed = " << moved
<< "\nObjects destroyed = " << destroyed;
return 0;
}