数组的结尾指向新分配的数组C ++

时间:2015-12-08 07:24:45

标签: c++ arrays

使用C ++,我试图创建一个数组,该数组包含指向我存储的对象的指针。但是当阵列已满时,我想扩展数组。

简单的选择是分配一个更大的新数组,然后将元素复制到它,这是非常低效的,我想到了另一种我想尝试的方式:

  1. 创建固定大小为X的数组

  2. 完整后,创建一个新数组,并使第一个数组的结尾指向第一个元素的开头

  3. 根据需要重复

  4. 我可以使用哪些方法来做到这一点?我想到了一种方法,但它似乎非常hacky:

    将我的所有新数组声明为指向对象指针的指针,然后将填充的元素reinterprit_cast转换为对象指针。

    注意:我知道我可以使用Vector,但我被告知不使用标准库


    亲切的问候,

3 个答案:

答案 0 :(得分:1)

  

使用C ++,我试图创建一个包含指针的数组   对象我存储。但是当数组已满时,我想扩展数组   阵列。

使用C ++模板和C基元,我们可以即兴创建一个简单的向量。增长缓冲策略是在达到阈值时将尺寸加倍。

#include <iostream>
#include <stdlib.h>

template <typename T>
class MyVector
{
   public:
      MyVector() : m_count(0), m_size(0), m_buffer(0)
      {
          m_size = bufInitSize;
          m_buffer = (T*)malloc(sizeof(T) * bufInitSize);
      }
      ~MyVector()
      {
         if (m_buffer)
            free(m_buffer);
      }
      void add(const T& p)
      {
         if (m_count + 1 >= m_size)
         {
             m_size *= 2;
             m_buffer = (T*)realloc(m_buffer, sizeof(T) * m_size);
         }
         m_buffer[m_count ++ ] = p;

      }
      T& operator[](int idx)
      {
         return m_buffer[idx];
      }

   private:
      static const int bufInitSize = 1024;
      T*  m_buffer;
      int m_count;
      int m_size;
};

void main()
{
   // using MyVector
   MyVector<int*> vctOfIntPtr;
   int n = 100;
   vctOfIntPtr.add(&n);
   int* pN = vctOfIntPtr[0];
   std::cout << *pN;
}

答案 1 :(得分:1)

评论中已有一些好的答案。我只想提供一种方法来实现完全您描述的行为。

由于数组的元素也是指针,你可以将union定义为数组的元素,如下所示:

template<typename T>
union Cell
{
    T* pElm;
    Cell* pNext;//A fixed size array of Cells
}

然后在它上面构建你的数组。例如:

template<typename T>
class SpecialArray
{
public:
    //the next pointer is included
    static const size_t ARRAY_LEN = 1000;// For example
    using Pointer = T*;
    using Segment = Cell<T>[ARRAY_LEN];

protected:
    Segment* pFirst;
    size_t mSize;

public:
    SpecialArray()
        :pFirst(nullptr),mSize(0){}
    SpecialArray(SpecialArray&&){}
    ~SpecialArray(){}

    Pointer& operator[](size_t index)
    {
        Segment* seg = pFirst;
        size_t offest = 0;
        //Search logic...

        return seg[offest]->pElm;
    }
    const Pointer& operator[](size_t index) const;
};

答案 2 :(得分:1)

另一个解决方案是存储大型固定大小的用户数据数组,然后您可以快速迭代。一些可能性:

std::vector<T*>data; // Using 1024-element arrays
int nStored = 0;
void push (T elem) {
  if (nStored%1024==0) {
    data.push_back(new T [1024]);
    data.back()[0] = elem;
  }
  else {
    data.back()[(nStored-1)%1024] = elem;
  }
  nStored++;
}
void pop () {
  if (nStored==0) return;
  if ((nStored-1)%1024==0) {
    delete data.back();
    data.pop_back();
  }
  nStored--;
}

std::list<T*>data;
int nStored = 0;
// Same push() and pop() as for vector<T*>

struct node {
  T* data;
  int sz;
  int last; // Index of last element stored
  const bool operator< (const node& o) const {
    return last<o.last;
  }
}
std::set<node> data;
int nStored = 0;
int capacity = 0;
void push (T elem) {
  if (nStored == capacity) {
    int nSize = 1024; // This doesn't have to be fixed, you could attach a
                    // more intelligent algorithm to it to optimise the 
                    // number of times you have to add and remove nodes.
    node n; n.sz = nSize; n.data = new T [n.sz]; n.last = nStored+nSize-1;
    data.insert(n);
    n.data[0] = elem;
    capacity += nSize;
  }
  else {
    node n,cNode; n.last = nStored;
    cNode = *data.lower_bound(n);
    cNode.data[nStored-(cNode.last-cNode.sz+1)] = elem;
  }
  nStored++;
}
void pop () {
  node n,cNode; n.last = nStored-1;
  cNode = *data.lower_bound(n);
  if ( (cNode.last+1-cNode.sz) == (nStored-1) ) {
    delete cNode.data;
    data.erase(data.lower_bound(n));
    capacity -= cNode.sz;
  }
  nStored--;
}
T& at (int idx) {
  if (idx<0 || idx>=nStored) throw;
  node n,cNode; n.last = idx;
  cNode = *data.lower_bound(idx);
  return cNode.data[idx-(cNode.last+1-cNode.sz)];
}

显然,您无法使用STL容器解决问题,但在C中实现它们非常简单。我只是用它们来说明。

所有这些可能性都基于拥有大型固定大小的用户数据数组的想法,然后能够以某种方式找到合适的数组。

前两个的at()函数相当简单,但我发现使用不同大小的数组的想法,如最后一种可能性所示,很有趣。这个想法的真正强大之处在于,您可以实现一种更有效的算法来分配固定大小的数组,而不仅仅是使它们保持不变的大小。

如果你使用&#39;设置&#39;如上所述,新节点的插入和删除是对数时间而不是摊销常数。但是,查找也是对数的。

使用&#39;向量&#39;会更好,因为插入和删除基本上是不变的,您可以二进制搜索向量以找到正确的节点。

使用&#39;列表&#39;仍会有不断的插入/删除但查找会更慢(因为你只能在列表中线性迭代)。

但出于实际目的,除非您处理绝对庞大的数据集,否则它不会产生巨大的差异