复制构造函数以进行非动态分配

时间:2013-11-19 12:27:36

标签: c++

根据定义:复制此类的对象时,会复制指针成员,但不会复制指向的缓冲区,从而导致两个对象指向相同的,因此我们使用复制构造函数。
但是在下面的课程中没有复制构造函数,但它有效!为什么?为什么我不需要深度复制?

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

3 个答案:

答案 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);

如果你复制它,你有两个指向同一个内存的指针,这本身不是问题,但是很难决定谁负责释放那个内存。