我有一个问题,我想在执行深层复制时克隆对象指针。 就像我有T * t1,我想以* t1.x = * t2.x的方式创建一个新的对象指针T * t2。
编写一个类似于:
的复制构造函数是一个好主意T(const T* cpy)
{
m_var = (*cpy).m_var;
}
T* t1 = new T;
T* t2(t1);
如果使用上述方法,我应该注意什么?
由于 Ruchi
答案 0 :(得分:4)
要做到这一点,你应该编写一个普通的拷贝构造函数并像这样使用它:
T(const T& cpy)
: m_var(cpy.m_var) // prefer initialization-list, thanks to @Loki Astari
{}
T* t1 = new T;
T* t2 = new T(*t1);
在您显示的代码中,T* t2(t1);
永远不会调用您声明的构造函数(顺便说一句,它不是复制构造函数),因为它只是将指针t2
初始化为指针t1
的值,使两者都指向同一个对象。
正如@Nawaz指出的那样,这个拷贝构造函数等同于编译器生成的拷贝构造函数,所以你实际上并不需要编写它。实际上,除非你有任何手动管理的资源(通常你不应该这样),你将始终可以使用编译器生成的复制构造函数。
答案 1 :(得分:1)
复制构造函数的定义需要引用,因此:
T(T const& copy) // This defines a copy constructor.
: m_var(copy.m_var) // Prefer to use the initializer list.
{}
所以你需要传递一个参考文献 如果要复制指针,则使用情况为:
T* t2 = new T(*t1);
答案 2 :(得分:0)
这不符合您的想法:
T* t2(t1);
因为你只是声明一个指针,而不是一个对象。指针初始化为另一个指针的值。它应该是:
T* t2 = new T (t1);
创建一个新对象。
对于副本,您当前正在执行浅拷贝,因为您只复制指针值,而不是指针指向的数据。当原始文件或副本被销毁时,执行浅拷贝会导致问题 - 如果删除m_var
,则另一个对象具有指向已删除内存的指针,如果是,则调用未定义行为 TM 解引用。深层复制修复了这个问题:
T(const T* cpy)
{
m_var = new VarType (cpy->m_var); // VarType being whatever m_var is
}
现在需要m_var
类型的复制构造函数,它也必须深入以防止上面的删除问题。
深度复制数据的缺点是它增加了内存需求,并花费大量时间来分配内存和复制数据。这可以使用引用计数对象来解决。这些有几种口味,智能指针是最常见的。这里,父对象的所有副本都引用相同的底层对象。删除父级时,对象的智能指针的析构函数仅在删除对其的所有引用时销毁基础对象。
智能指针的缺点是,从一个拥有对象更改数据会修改所有拥有对象将看到的数据。为了获得两全其美,您需要拥有“修改后的复制”系统。这只会在拥有对象修改基础数据时增加内存使用量。