Как я могу изменить функцию, которая использует allocator :: allocate, чтобы она использовала unique_ptr вместо необработанного указателя? - PullRequest
0 голосов
/ 20 июня 2020

Я работаю над Программой: принципы и практика (2-е издание) Бьярна Страуструпа самостоятельно. В одном из упражнений «Попробуйте это» вас попросят изменить приведенную ниже функцию vector1<T, A>::reserve(int newalloc), заменив необработанный указатель на unique_ptr. Функция резервирования предназначена для заимствования неинициализированного пространства из бесплатного хранилища, которое затем можно инициализировать с помощью push_back () и resize ().

Я попытался просто заменить T*p на unique_ptr<T> p, но это дает следующие три сообщения об ошибках:

  1. «преобразование из '__gnu_cxx :: new_allocator :: pointer' {aka 'int *'} в нескалярный тип 'std :: unique_ptr>' запрошено» (для строки unique_ptr<T> p = alloc.allocate(newalloc);)

  2. "нет соответствия для 'operator []' (типы операндов - 'std :: unique_ptr>' и 'int')" (для строки elem = p;)

  3. «невозможно преобразовать '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)
...