重载赋值操作operator=()

参考:Effective C++以及http://www.cnblogs.com/dahai/archive/2011/04/11/2012519.html

C++认的赋值操作是按成员赋值(包括指针,嵌套的类成员等)

如果类成员都为值类型时,工作良好;

但特殊情况下,这种操作往往会有问题。

下面例子是类成员包含指针成员时,使用默认的赋值操作时,导致了内存被重复释放的问题

代码如下:

#include "stdafx.h"
#include <string>

using namespace std;

class A
{
private:
    char *p;
    size_t nSize;

public:
    A(const string &str);
    ~A();
};
...
int _tmain(int argc, _TCHAR* argv[])
{
    A obj1("hello");
    A obj2("world");

    //赋值操作
    obj2 = obj1;
    system("pause");
    return 0;
}
运行会出错!

原因是:采用默认的赋值操作后,obj1.p和obj2.p的成员变量p都指向了同一块内存,这样析构时就对同一块内存释放了两次。

我们赋值的真正意思可能是,两个对象各有自己的一块内存,互不相干,只是复制其中的内容。这时候就需要重载赋值操作符operator=()了。

正确的做法:

#include <string.h>
 
class A
{
private:
    char * m_pointer;
    size_t m_nSize;

public:
    //重载赋值操作符(默认的"="会使类成员指针和返回对象中的成员指针指向同一地址)
    A& operator=(const A &a);

public:
    A(const char * cStr, const int strLen);
    ~A();
};
 
A::A(const char * cStr, const int strLen)
{
    p = new char[strLen + 1];
    memset(p, 0, strLen+1);
    strcpy(p, cStr);
    nSize=strLen;
}
 
A::~A()
{
    delete[] p;
}
 
//此做法是Effective C++推荐的做法
inline A& A::operator=(const A &a)
{
    char * tempPointer=a.p;

    //即时new操作有异常而返回,p也会指向原地址(切记)
    this->p = new char[a.nSize + 1];
    strcpy(this->p, a.p);

    delete[] tempPointer;

    return * this;
}
 
int main()
{
    A obj1("hello", strlen("hello"));
    A obj2("world", strlen("world"));

    //赋值操作(obj2调用operator=()方法)
    obj2 = obj1;

    return 0;
}

注意事项:

1> obj2=obj1; 实际上是由obj2调用operator=()方法,所以返回值为:*this

2> 在operator=()方法中,由于参数也是A类型,所以可以访问其私有成员变量;

3> 在operator=()方法中,this->p=new char[]中,如果new操作失败,则this->p仍然会指向原地址;

4> 若不希望用户对该类对象进行赋值操作,则可以重载赋值操作符为private;

5> 返回类型为:A &,即引用;

返回引用类型,个人感觉应该是基于如下两个原因:

 (1) obj2调用operator=()方法,其不用担心声明周期的问题;

(2) 如果返回类型是值类型,而不是引用的话,则现在的obj2是(原obj2,即调用operator()=的obj2,在重新赋值后)的一个复制品,也就是返回的obj2和调用opertor=()的obj2,其p都指向了同一块内存空间;从而导致重复释放同一片内存空间的错误!

你可能感兴趣的:(c,工作,String,delete,System,Class)