Я работаю над Программой: принципы и практика (2-е издание) Бьярна Страуструпа самостоятельно. В одном из упражнений «Попробуйте это» вас попросят изменить приведенную ниже функцию vector1<T, A>::reserve(int newalloc)
, заменив необработанный указатель на unique_ptr
. Функция резервирования предназначена для заимствования неинициализированного пространства из бесплатного хранилища, которое затем можно инициализировать с помощью push_back () и resize ().
Я попытался просто заменить T*p
на unique_ptr<T> p
, но это дает следующие три сообщения об ошибках:
«преобразование из '__gnu_cxx :: new_allocator :: pointer' {aka 'int *'} в нескалярный тип 'std :: unique_ptr>' запрошено» (для строки unique_ptr<T> p = alloc.allocate(newalloc);
)
"нет соответствия для 'operator []' (типы операндов - 'std :: unique_ptr>' и 'int')" (для строки elem = p;
)
«невозможно преобразовать 'std :: unique_ptr>' в 'int *' в присваивании» (для строки alloc.construct(&p[i], elem[i]);
)
Любая помощь в получении reserve
для использования unique_ptr
будет очень принята. Я очень новичок в концепции уникальных указателей и allocator::allocate
, но, похоже, проблема связана с попыткой преобразовать / назначить необработанный указатель из allocator::alocate
моему уникальному указателю. Если есть способ заставить мою функцию reserve
работать без использования allocator::allocate
, я весь уши.
Я также не прочь изменить elem
на unique_ptr
( который, как мне кажется, решит третью ошибку компилятора), но я не думаю, что это решило бы проблему с allocator::allocate
.
Заранее спасибо!
//Much of the following code is from Programming: Principles and Practice Using C++ (2nd ed., 3rd printing) by Bjarne Stroustrup. The code is an example of a template similar to the actual Standard Library vector.
#include <iostream>
#include <memory>
using namespace std;
template <typename T, typename A = allocator<T>>
class vector1 //Used "vector1" instead of "vector" to make sure the compiler wouldn't confuse this vector and the actual Standard Library vector.
{
A alloc;
int sz;
T *elem;
int space;
public:
vector1() : sz{0}, elem{nullptr}, space{0} {}
explicit vector1(int s) : sz{s}, elem{new T[s]}, space{s}
{
for (int i = 0; i < sz; ++i)
elem[i] = 0; //Initializes all elements
}
vector1(const vector1&);
vector1& operator = (const vector1&);
vector1(vector1&&);
vector1& operator=(vector1&&);
~vector1() { delete[] elem; }
T& operator[] (int n) {return elem[n];}
const T& operator[] (int n) const{return elem[n];}
int size() const { return sz; }
int capacity() const { return space; }
void resize(int newsize)
{
reserve(newsize);
for (int i = sz; i < newsize; ++i)
elem[i] = 0;
sz = newsize;
}
void push_back(const T& d);
void reserve(int newalloc);
};
template <typename T, typename A>
void vector1<T, A>::reserve(int newalloc)
{
if (newalloc <= space)
return;
T* p = alloc.allocate(newalloc);
for (int i = 0; i < sz; ++i)
alloc.construct(&p[i], elem[i]);
for (int i = 0; i < sz; ++i)
alloc.destroy(&elem[i]);
alloc.deallocate(elem, space);
elem = p;
space = newalloc;
}
template<typename T, typename A> void sizereport(vector1<T,A> &v) //Makes it easier to see the current size and memory allocation of a given vector
{
cout << "Size is " << v.size() << " and capacity is " << v.capacity() << ".\n";
}
int main()
{
vector1<int> v1;
sizereport(v1);
v1.reserve(10);
sizereport(v1);
}
(Примечание: приведенный выше код компилируется правильно и дает следующий результат:
Size is 0 and capacity is 0. //Before v1.reserve(10)
Size is 0 and capacity is 10.) //After v1.reserve(10)