根据定义:复制此类的对象时,会复制指针成员,但不会复制指向的缓冲区,从而导致两个对象指向相同的,因此我们使用复制构造函数。
但是在下面的课程中没有复制构造函数,但它有效!为什么?为什么我不需要深度复制?
class Human
{
private:
int* aValue;
public:
Human(int* param)
{
aValue=param;
}
void ShowInfos()
{
cout<<"Human's info:"<<*aValue<<endl;
}
};
void JustAFunction(Human m)
{
m.ShowInfos();
}
int main()
{
int age = 10;
Human aHuman(&age);
aHuman.ShowInfos();
JustAFunction(aHuman);
return 0;
}
输出:
人类信息:10
人类信息:10
答案 0 :(得分:6)
当您的类拥有资源时,复制构造函数很有用。在你的情况下,它不会 - 它既不会创建也不会删除aValue
本身。
如果你这样做了,请说:
Human()
{
aValue=new int;
}
并正确清理内存:
~Human()
{
delete aValue;
}
然后你会遇到问题,因为Human a;
和Human b(a);
会让成员aValue
指向同一个位置,当他们超出范围时,同样的记忆被释放,导致双重删除。
答案 1 :(得分:3)
正如已经提到的,它适用于你的原因是让多个指针指向同一个对象实际上很好 - 这就是重点,共享数据而不复制它。
如果指向的对象的生命周期由包装类管理,问题就会到来,即:它是在类实现的方法中创建和销毁的 - 通常是类的构造函数和析构函数。在这种情况下,复制构造函数中需要deep copy。
在你的(公认的设计)示例中,int具有更长的生命周期,携带指针的对象应该使用引用作为成员进行检查,在初始化列表中初始化。这消除了忘记自己并从课堂中删除对象的可能性。
class Human
{
private:
int& aRef;
public:
Human(int& param)
: aRef(param)
{
}
};
您还应该考虑指针或引用是否应该是const对象:
class Human
{
private:
const int& aRef;
public:
Human(const int& param)
: aRef(param)
{
}
};
答案 2 :(得分:2)
这是有效的,因为类中的指针指向堆栈变量age
。
您尚未为类Human
编写析构函数,因此在Human
中复制JustAFunction
时不会尝试进行双重删除
如果您使用它的方式不同,例如将new
ed int发送到类中,则会发生内存泄漏。
Human human(new int);
如果你复制它,你有两个指向同一个内存的指针,这本身不是问题,但是很难决定谁负责释放那个内存。