如何实现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向量来完成任务,但出于实验目的,我正在编写一个完全相同的模板类。
感谢。
答案 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
调用T
。 push_back
实现应该(必须)调用copy-constructor或赋值运算符。应该分配内存来保存那些被推送的元素。初始内存分配不应该调用类型为T的CTOR。例如:
T* pArray;
pArray = (T*) new BYTE[sizeof(T) * INITIAL_SIZE);
然后将新对象放入pArray,调用赋值运算符。