Как выделить, так и сконструировать, зачем нужны два?
Я провел некоторое исследование, но у меня все еще есть несколько вопросов, потому что вещи не кажутся ясными, есть еще одно обсуждение, которое здесь похоже, но неясно, дан один ответ, но у него репутация ноль, и единственный комментарий говорит что ответ не правильный.
Итак, во-первых, почему std::allocate
есть две функции, которые, кажется, делают то же самое? deallocate
а также destroy
, Из того, что я читал в C++ о создании объектов за кулисами, сначала вызывается malloc, который выделяет достаточно памяти для объекта (ов), который вы хотите, затем new создает этот объект,
но это все еще оставляет вопрос: зачем нам нужно и уничтожать, и освобождать, а также распределять и конструировать? При вызове нового ключевого слова malloc сначала выполняется d, затем объект создается в этой памяти, поэтому, если об этом позаботится с новым ключевым словом, зачем нам нужны две функции (allocate и construct), почему мы не можем просто иметь функцию называется конструкция, которая вызывает новое ключевое слово
и иметь функцию destroy, которая освобождает и удаляет объект, который делает ключевое слово delete
***Редактировать*
в функции изменения размера почему мы вызываем только destroy, но не освобождаем?
а в резервной функции мы называем и уничтожить, и освободить?
обратите внимание, что это не мой код, но реализация вектора Бьярнса
Спасибо, парни
#include <iostream>
using namespace std;
template <class T,class A = allocator<T> > class Vector{
A alloc;
int size;
int space;
T *elem;
public:
Vector(int size)
: size(size),elem(new T[size])
{
space = size;
for(int i = 0; i < size; i++){
elem[i] = 0;
}
}
Vector(){
size = 0;
elem = 0;
space = 0;
}
Vector(const Vector& other)
{
size = other.size;
elem = new T[other.size];
copyValues(other);
}
void copyValues(const Vector& other){
for(int i = 0; i < size; i++){
elem[i] = other.elem[i];
}
}
Vector& operator=(const Vector& other){
T *p = new T[other.size];
for(int i = 0; i < other.size; i++){
p[i] = other.elem[i];
}
delete[] elem;
elem = p;
size = other.size;
return *this;
}
T& operator[](int i){
return elem[i];
}
T operator[](int i)const{
return elem[i];
}
int vectorSize(){
return size;
}
void reserve(int amount){
if(amount <= space){
return;
}
T *p = alloc.allocate(amount);
for(int i = 0; i < size; i++){
alloc.construct(&p[i],elem[i]);
}
for(int i = 0; i < size; i++){
alloc.destroy(&elem[i]);
}
alloc.deallocate(elem,space);
elem = p;
space = amount;
}
void resize(int newSize,T val = T()){
reserve(newSize);
for(int i = size; i < newSize; i++){
alloc.construct(&elem[i],val);
}
for(int i = newSize; i < size; i++){
alloc.destroy(&elem[i]);
}
size = newSize;
}
void push_back(const T& val){
if(space == 0){
reserve(8);
}
if(size == space){
reserve(2 * space);
}
alloc.construct(&elem[size],val);
size++;
}
};
class hey{
public:
int a;
int b;
hey(){
a = 7;
b = 7;
}
hey(int x,int y){
a = x;
b = y;
}
hey(const hey& other){
a = other.a;
b = other.b;
}
hey& operator=(const hey& other){
a = other.a;
b = other.b;
return (*this);
}
};
int main()
{
Vector<hey> sample;
hey h(5,3);
hey b(7,3);
hey c(8,2);
sample.push_back(h);
sample.push_back(b);
sample.push_back(c);
sample[0].a = 9;
for(int i = 0; i < sample.vectorSize(); i++){
cout << sample[i].a << endl;
}
}
1 ответ
TL;DR. Распределитель должен предоставлять две отдельные функции, allocate
а также construct
потому что они делают две разные работы.
Много контейнеров (std::vector
было бы очень ярким примером) выделить больше памяти, чем им нужно для хранения текущего количества элементов. Это называется резервированием памяти и используется в целях эффективности - обычно гораздо лучше выделить один большой кусок памяти, чем несколько меньших. Вот почему распределители предоставляют allocate
- так что контейнеры могут захватить кусок памяти.
Позже, когда элементы добавляются в контейнер, он должен использовать эту зарезервированную память для создания элемента в нем - и это то, что construct
для.
deallocate
а также destruct
как раз наоборот - deallocate
используется, когда вектор готов освободить память, и destruct
используется, чтобы уничтожить объект, но сохранить память.