创建一个C ++模板类,它可以像Vector of Vectors

时间:2018-05-28 13:41:47

标签: c++ arrays templates vector

这是一个Group类,类似于Vector。我可以创建一个组的矢量,并且工作正常。我在创建群组时遇到了困难。此代码编译并运行,但组的行为与组向量的行为不同 - 请参阅输出。我觉得我在Group中缺少一个处理模板类型的特殊构造函数?也许它是别的东西 - 任何指针都感激不尽。

#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 :(得分:0)

有两件事需要解决:

  • 正如评论中建议的那样,您需要在构造函数中设置current_size
  • 您需要与operator[]一起返回引用,否则所有修改都将应用于元素的临时副本

link to the code

答案 1 :(得分:0)

你班上有一个非平凡的析构函数。这意味着默认的复制构造函数和默认的复制赋值将会出错。

这是一个简单的例子:

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的规则(更多细节here

如果您不实现它们,编译器将隐含地提供移动ctor和移动赋值运算符,它不会比复制版本工作得多。因此,您必须实现它们或将它们标记为明确删除 - 这是5的规则。

容器的推荐operator [] - 标准库使用的是:

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

使用引用可以避免不必要的大对象副本......