Создайте шаблонный класс C ++, который может работать как Вектор Векторов - PullRequest
0 голосов
/ 28 мая 2018

Это групповой класс, похожий на вектор.Я могу создать вектор групп, и это прекрасно работает.У меня проблемы с созданием групп групп.Этот код компилируется и запускается, но группа групп не ведет себя так же, как вектор групп - смотрите вывод.Я чувствую, что мне не хватает специального конструктора в группе, который обрабатывает шаблонные типы?Возможно, это что-то еще - с благодарностью получили любые указатели.

#include <vector>

template <class T>
class Group
{
  private:
    T *data;
    int current_size;
    int max_size;

  private:
    void expand();

  public:
    Group();
    Group(int size);
    ~Group();

    T operator[](int index) const;
    int count() const;
    int add_item(const T new_item);
};

template <class T>
Group<T>::Group()
{
    data = NULL;
    max_size = 0;
    current_size = 0;
}

template <class T>
Group<T>::Group(int size)
{
    if (size < 2)
        size = 2;
    data = new T[size];
    max_size = size;
    current_size = 0;
}

template <class T>
Group<T>::~Group()
{
    if (data != NULL)
        delete[] data;
    current_size = 0;
    max_size = 0;
}

template <class T>
void Group<T>::expand()
{
    if (data == NULL)
    {
        current_size = 0;
        max_size = 2;
        data = new T[2];
    }
    else
    {
        //      printf("expanding %x from %d to %d\n", this, current_size, current_size*2);

        T *tempArray = new T[max_size * 2];
        for (int i = 0; i < max_size; i++)
        {
            tempArray[i] = data[i];
        }

        delete[] data;
        data = tempArray;
        max_size = max_size * 2;
    }
}

template <class T>
int Group<T>::add_item(const T new_item)
{
    // expand the array if necessary
    while (current_size >= (max_size))
        expand();

    // add_item the new thing
    data[current_size] = new_item;
    current_size++;
    return (current_size);
}

template <class T>
inline T Group<T>::operator[](int index) const
{
    return data[index];
}

template <class T>
inline int Group<T>::count() const
{
    return current_size;
}

int main()
{
    // Vector of Groups works fine

    int numgroups = 3; // just 3 groups for testing

    // a vector of Groups
    std::vector<Group<int>> setofgroups(numgroups);

    printf("setofgroups count=%d\n", setofgroups.size());

    // some test data
    // 4 items in first group
    setofgroups[0].add_item(6);
    setofgroups[0].add_item(9);
    setofgroups[0].add_item(15);
    setofgroups[0].add_item(18);

    // one item in second
    setofgroups[1].add_item(7);

    // two items in third
    setofgroups[2].add_item(8);
    setofgroups[2].add_item(25);

    // for each group, print the member values
    for (int g = 0; g < setofgroups.size(); g++)
    {
        printf("group %d\n", g);
        for (int i = 0; i < setofgroups[g].count(); i++)
            printf("  member %d, value %d\n", i, setofgroups[g][i]);
    }

    // Group of groups doesn't seem to work

    Group<Group<int>> groupofgroups(numgroups);

    // this returns ZERO - not 3 as I expected
    printf("groupofgroups count=%d\n", groupofgroups.count());

    groupofgroups[0].add_item(6);
    groupofgroups[0].add_item(9);
    groupofgroups[0].add_item(15);
    groupofgroups[0].add_item(18);

    printf("groupofgroups[0].count=%d\n", groupofgroups[0].count()); // this returns ZERO - where did the items go?

    groupofgroups[1].add_item(7);

    // two items in third
    groupofgroups[2].add_item(8);
    groupofgroups[2].add_item(25);

    // for each group, print the member values
    for (int g = 0; g < groupofgroups.count(); g++)
    {
        printf("group 2  %d (count=%d)\n", g, groupofgroups[g].count());
        for (int i = 0; i < groupofgroups[g].count(); i++)
            printf("  member %d, value %d\n", i, groupofgroups[g][i]);
    }

    return 0;
}

Выход:

       setofgroups count=3
    group 0
      member 0, value 6
      member 1, value 9
      member 2, value 15
      member 3, value 18
    group 1
      member 0, value 7
    group 2
      member 0, value 8
      member 1, value 25
    groupofgroups count=0

groupofgroups[0].count=0

Ответы [ 2 ]

0 голосов
/ 28 мая 2018

У вас есть нетривиальный деструктор в вашем классе.Это означает, что конструктор копирования по умолчанию и назначение копирования по умолчанию сделают неправильную вещь.

Вот простой пример:

Group<int> a(4);  // ok, ready to add some elements in the freshly allocated a.data
a.add_item(1);
int count = a.add_item(2);   // ok a contains 2 items 1 and 2

if (count == 2) {
    Group<int> b = a;        // the default copy ctor make b.data == a.data...
    std::cout << "b contains " << b.count() << " items" << std::endl; // nice up to here
}             // horror: b reaches end of life and destructor calls delete[](b.data) !

// a.data is now a dangling pointer...

Таким образом, вы должны либо реализовать конструктор копирования, либо копиюоператор присваивания или пометить их как явно удаленные - это правило 3 (более подробно здесь )

Если вы не реализуете их, компилятор неявно предоставит ctor перемещения и назначение Moveоператор, который не работает намного больше, чем копия версии.Таким образом, вы должны реализовать их или пометить их как явно удаленные - это правило 5.

И рекомендуемый operator [] для контейнеров - которые используют стандартные библиотеки - это:

T& operator[] (size_t index);              // used for  a[i] = ...
const T& operator[] (size_t index) const;  // used for  x = a[i];

Использование ссылок может избежать ненужных копий больших объектов ...

0 голосов
/ 28 мая 2018

Есть 2 вещи, которые нужно исправить:

  • , как указано в комментарии, вам нужно установить current_size в конструкторе
  • , вам нужно вернуть ссылку с собой operator[]иначе все изменения будут применены к временной копии элемента

ссылка на код

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...