重载赋值号的问题?为什么不能自赋值

本文分析了C++中自赋值运算符的问题,重点讨论了为何不能直接自赋值,并通过实例讲解了内存释放与重载赋值操作的正确实践。作者探讨了指针改变和资源管理的重要性,以及两种避免内存泄露的解决方案:检查指针是否为自身和临时指针赋值策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

重载赋值号的问题?为什么不能自赋值

#include <iostream>
#include <string.h>
#include <cstring>
using namespace std;
class A
{
public:
    char *ptr;
    void set_ptr(char *str)
    {
        ptr = new char[strlen(str) + 1];
        strcpy(ptr, str);
    }
    A &operator=(const A &rhs)
    {
        cout << "rhs.ptr1:  " << rhs.ptr << endl;

        this->ptr = new char[strlen(rhs.ptr) + 1];
        cout << "rhs.ptr:  " << rhs.ptr << endl;
        cout << "this->ptr:" << this->ptr << endl;
        
        return *this;
    }
};
int main()
{
    A a;
    char *name = (char *)"hello world";
    a.set_ptr(name);

    a = a;
    // 等效于a.operator=(a);
    cout <<"a.ptr2: "<<a.ptr<<endl;
    
}

运行结果如下:
rhs.ptr1:  hello world
rhs.ptr:  
this->ptr:
a.ptr2: 

分析一下程序:

这是一个赋值号的重载函数,功能是:对象能直接赋值另一个对象。这个重载运算符的函数并不完整,只为说明问题。

这里是自赋值,即a对象赋值给a对象。 但我们可以发现, 在执行 this-> ptr = new char[strlen(rhs.ptr) + 1]; 之前。rhs.ptr的值是 hello world

而执行完 this-> ptr = new char[strlen(rhs.ptr) + 1]; 之后再次执行 cout << "rhs.ptr: " << rhs.ptr << endl; 打印rhs.ptr 发现结果是空,

执行cout << “this->ptr:” << this->ptr << endl;,this .ptr也是空。但我并没有主动调用delete去释放空间。原因就是指针改变了指向,导致指针指向了未知的新的空间,而新的空间没有任何东西

this->ptr = new char[strlen(rhs.ptr) + 1]; 翻译一下

new一块和rhs.str大小一样的空间,然后返回一个变了的地址给this.str,也就是说a.str的地址变了,rhs是a的引用,不是指针,所以rhs.str自然也就是a.str,也改变了。也就是重置了指针指向。

另一种情况如下:

另一个更重要的原因是保证正确性。一个赋值运算符必须首先释放掉一个对象的资源(去掉旧值),然后根据新值分配新的资源。在自己给自己赋值的情况下,释放旧的资源将是灾难性的,因为在分配新的资源时会需要旧的资源。

如下面的代码:

#include<iostream>
#include<string>
#include<string.h>
using namespace std;
class A
{
public:
    char *ptr;
    A(){ptr = nullptr;}
    void set_ptr(char *str){ptr = new char[strlen(str)+1]; strcpy(ptr,str);}
    A& operator=(const A&rhs)
    {
        
        delete this->ptr;
        this->ptr = new char[strlen(rhs.ptr)+1];
        strcpy(this->ptr,rhs.ptr);
        return *this;
    }
};
int main()
{
    A a;
    char*name=(char*)"hello world";
    a.set_ptr(name);
    a = a;
    cout<<a.ptr<<endl;
}

执行完delete this->ptr;之后,rhs.ptr 的指向就悬空了。对此我们有两种解决方法:

下面有几种办法
1、判断参数是否是自身
那么就要重载==或者!=运算符
if(*this != rhs)
该运算符不止要判断数据成员的值是否相等
还要判断ptr的指向(即ptr的指针值是否相等)
那么这样的运算符失去了一般性(没必要判断ptr的指针值是否相等,而是判断指向的内容是否相等)

所以简化的方法就是 if (this == &m_point) // 不能if(*thism_point)因为同地址必然同值,但同值不一定同地址,除非按上述的所说的重载

    if (this == &m_point) //  不能if(*this==m_point)因为同地址必然同值,但同值不一定同地址
            return *this;
     
        str = new char[strlen(m_point.str) + 1];
        strcpy(str, m_point.str);
        return *this;
        delete[] str;//防止内存泄漏

2.2、即先将右操作数的内容赋值到一个临时指针
然后释放左操作数指针指向的内存
然后将临时指针赋给左操作数的指针

    
class A
{
public:
    char *ptr;
    A(){ptr = nullptr;}
    void set_ptr(char *str){ptr = new char[strlen(str)+1]; strcpy(ptr,str);}
    A& operator=(const A&rhs)
    {

    char *temp = new char[strlen(rhs.ptr)+1];//复制资源到一个临时指针
    strcpy(temp,rhs.ptr);
    delete ptr;
    ptr = temp;
 
    return *this;
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丁金金_chihiro_修行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值