重载赋值操作operator=()

来源:互联网 发布:mac点击下载后没反应 编辑:程序博客网 时间:2024/06/05 02:51

参考: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都指向了同一块内存空间;从而导致重复释放同一片内存空间的错误!

原创粉丝点击