从指针或指针链复制数据(对象指针,模板)

时间:2011-06-24 05:13:08

标签: c++ templates vector copy-constructor

如何实现push_back stl::vector以便它可以复制任何数据类型..可能是指针,双指针等等......

我正在实现一个模板类,其函数push_back几乎与向量类似。在此方法中,应在内部分配的内存中插入参数的副本。

如果参数是指针或指针链(对象指针);副本应该由指向的实际数据组成。 [根据评论更新]

你能告诉我如何从指针创建副本。所以,如果我删除调用者中的指针仍然复制存在于我的模板类中?

代码库如下:

template<typename T>
class Vector
{
    public:
        void push_back(const T& val_in)
        {
            T a (val_in); // It copies pointer, NOT data.
            m_pData[SIZE++] = a; 
        }
}

Caller:

// Initialize my custom Vector class.
Vector<MyClass*> v(3);

MyClass* a = new MyClass();
a->a = 0;
a->b = .5;

// push MyClass object pointer
// now push_back method should create a copy of data 
// pointed by 'a' and insert it to internal allocated memory.
// 'a' can be a chain of pointers also.

// how to achieve this functionality?
v.push_back(a);

delete a;

我可以简单地使用STL向量来完成任务,但出于实验目的,我正在编写一个完全相同的模板类。

感谢。

5 个答案:

答案 0 :(得分:1)

如果你有多态对象(指向的对象可能比变量更专业),我建议你创建一个名为clone()的虚方法,它分配一个带有你对象副本的新指针:

Base* A::clone() {
    A* toReturn = new A();
    //copy stuff
    return toReturn;
}

如果您无法修改Base类,则可以使用RTTI,但我不会在此答案中使用此解决方案。 (如果您想在此解决方案中获得更多详细信息,请使用RTTI提出有关多态克隆的问题。)

如果您没有多态对象,可以通过调用复制构造函数来分配新对象。

void YourVector::push_back(Base* obj) {
    Base* copy = new Base(obj);
}

但它闻起来你真正需要的是shared_ptr,可以在<tr1/memory>中使用(如果使用C ++ 0x,则为<memory>。)

根据评论更新

您可能还有两个模板参数列表:

template <typename T>
struct CopyConstructorCloner {
    T* operator()(const T& t) {
        return new T(t);
    }
}

template <typename T, typename CLONER=CopyConstructorCloner<T> >
class MyList {
    CLONER cloneObj;
public:
    // ...
    void push_back(const T& t) {
        T* newElement = cloneObj(t);
        // save newElemenet somewhere, dont forget to delete it later
    }
}

通过这种方法,可以为指针等事物定义新的克隆政治。

不过,我建议您使用shared_ptrs。

答案 1 :(得分:0)

一种解决方案是制作复制结构:

MyClass *p = new MyClass();
MyVector<MyClass*> v;
v.push_back(new MyClass(*p));

更新:从您更新的问题中,您绝对可以覆盖push_back

template<typename T>
class MyVector {
public:
  void push_back (T obj); // general push_back
  template<typename TYPE>  // T can already be a pointer, so declare TYPE again
  void push_back (TYPE *pFrom)
  {
    TYPE *pNew = new TYPE(*pFrom);
    // use pNew in your logic...
  }
};

答案 2 :(得分:0)

我认为对于这类问题,最好使用智能指针ex:boost :: shared_ptr或任何其他等效实现。

答案 3 :(得分:0)

这样的事情:

template<typename T>
class MyVector
{
    T*     data;          // Pointer to internal memory
    size_t count;         // Number of items of T stored in data
    size_t allocated;     // Total space that is available in data
                          // (available space is => allocated - count)

    void push_back(std::auto_ptr<T> item) // Use auto pointer to indicate transfer of ownership
    /*void push_back(T* item) The dangerous version of the interface */
    {
        if ((allocated - count) == 0)
        {    reallocateSomeMemory();
        }

        T*   dest = &data[count];  // location to store item

        new (dest) T(*item);       // Use placement new and copy constructor.
        ++count;
    }

    // All the other stuff you will need.
};

根据评论进行编辑:

要调用它,您需要这样做:

MyVector<Plop>    data;

std::auto_ptr<Plop>   item(new Plop());   // ALWAYS put dynamically allocated objects
                                          // into a smart pointer. Not doing this is bad
                                          // practice.
data.push_back(item);

我使用auto_ptr因为RAW指针很糟糕(即在真正的C ++代码中(与C不同)你很少看到指针,它们隐藏在智能指针中。)

答案 4 :(得分:0)

无需为给定的数据类型new调用Tpush_back实现应该(必须)调用copy-constructor或赋值运算符。应该分配内存来保存那些被推送的元素。初始内存分配不应该调用类型为T的CTOR。例如:

   T* pArray; 
   pArray = (T*) new  BYTE[sizeof(T) * INITIAL_SIZE);

然后将新对象放入pArray,调用赋值运算符。