加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

运算符重载返回对象导致内存泄漏,C

发布时间:2020-12-16 10:39:31 所属栏目:百科 来源:网络整理
导读:我认为问题是当我重载操作符时返回一个对象.我尝试返回对该对象的引用,但这样做并不能解决内存泄漏问题.我可以评论这两个陈述: dObj = dObj + dObj2; 和 cObj = cObj + cObj2; 释放内存泄漏程序.不知何故,问题是在重载操作符后返回一个对象. #include iostr
我认为问题是当我重载操作符时返回一个对象.我尝试返回对该对象的引用,但这样做并不能解决内存泄漏问题.我可以评论这两个陈述:

dObj = dObj + dObj2;

cObj = cObj + cObj2;

释放内存泄漏程序.不知何故,问题是在重载操作符后返回一个对象.

#include <iostream>
    #include <vld.h>

    using namespace std;

    class Animal
    {
    public :
        Animal() {};
        virtual void eat()  = 0 {};
        virtual void walk() = 0 {};
    };

    class Dog : public Animal
    {
    public :
        Dog(const char * name,const char * gender,int age);
        Dog() : name(NULL),gender(NULL),age(0) {};

        virtual ~Dog();
        Dog operator+(const Dog &dObj);

    private :
        char * name;
        char * gender;
        int age;
    };

    class MyClass
    {
    public :
        MyClass() : action(NULL) {};
        void setInstance(Animal &newInstance);
        void doSomething();

    private :
        Animal * action;
    };


    Dog::Dog(const char * name,int age) :  // allocating here,for data passed in ctor
            name(new char[strlen(name)+1]),gender(new char[strlen(gender)+1]),age(age)
    {
        if (name)
        {
            size_t length = strlen(name) +1;
            strcpy_s(this->name,length,name);
        }
        else name = NULL;
        if (gender)
        {
            size_t length = strlen(gender) +1;
            strcpy_s(this->gender,gender);
        }
        else gender = NULL;
        if (age)
        {
            this->age = age;
        }
    }
    Dog::~Dog()
    {
        delete name;
        delete gender;
        age = 0;
    }

    Dog Dog::operator+(const Dog &dObj)
    {
        Dog d;
        d.age = age + dObj.age;
        return d;
    }

    void MyClass::setInstance(Animal &newInstance)
    {
        action = &newInstance;
    }
    void MyClass::doSomething()
    {
        action->walk();
        action->eat();  
    }
    int main()
    {
        MyClass mObj;

        Dog dObj("Scruffy","Male",4); // passing data into ctor
        Dog dObj2("Scooby",6);

        mObj.setInstance(dObj); // set the instance specific to the object.
        mObj.doSomething();  // something happens based on which object is passed in

        dObj = dObj + dObj2; // invoke the operator+ 
        return 0;
    }

解决方法

你需要声明复制构造函数,因为你在重载操作符中返回对象,如果你没有明确定义它,编译器会自动为你生成一个,但编译器是愚蠢的,不能对指针进行深层复制

在发布的代码中总结您的错误:

1.)没有Copy-Constructor / Assignment-Operator定义(释放异常/内存泄漏)
由于您正在处理指针,因此编译器生成的函数仅执行浅拷贝.
确保此类行为是有意为您的工作,否则请将其自行重新定义为:

Dog::Dog(const Dog& ref) :
_name( strdup(ref._name) ),_gender( strdup(ref._gender) ),_age( ref._age )
{
}

Dog& Dog::operator=(const Dog &dObj)
{
    if (this != &dObj)
    {
        free (_name);
        free (_gender);
        _name = strdup( dObj._name );
        _gender = strdup( dObj._gender );
        _age = dObj._age;
    }
    return *this;
}

2.)传入指针的处理不当(这里是内存泄漏)
您在验证输入参数的空状态之前执行了分配.
另外额外分配1个内存char是明智之举,但是在找到输入参数为null之后你不会释放它们.类似于上面的copy-constructor的简单修复将是:

Dog::Dog(const char * name,int age) :
_name( strdup(name) ),_gender( strdup(gender) ),_age( age )
{
}

3.)分配器/解除分配器配对不当(此处存在潜在的内存泄漏)
使用new []的数组分配应该与数组释放delete []匹配,否则将无法正确处理数组元素的析构函数.
但是,为了与上面使用strdup(内部使用malloc)发布的示例代码一致,您的析构函数应如下所示:

Dog::~Dog()
{
    free (_name);
    free (_gender);
    _age = 0;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读