linux平台C++中拷贝构造函数及“=”重载的理解

这段时间在学习C++,虽然以前学过,但学校里学的和真正的用起来还是有差距的,写程序的时候发现自己知道的还是太少了,在学习的过程中,发现了一些问题,在这里总结一下,以备以后查看。同时也供大家拍砖。。。


环境:ubuntu11.10

编译器:g++4.6.1



我们先定义一个类把:

class String

{

       private:

                     intm_len;

                     char*m_str;  //定义了3个私有成员变量 ,这里是个指针

                     staticint num;

                    

       public:

                     String();//构造函数

                     ~String();//析够函数

                    

                     friendostream &operator<<(ostream &,String &); //重载<<

                    

  String(constString &); //拷贝函数  拷贝函数的定义是(const String &)  不能是//(String &),一定不能少了const,少了会报错

                    

                     String(constchar*); //普通类型—>类类型转换

                    

                     String&operator=(const char *);//实现 String t;  t="chenyu" 这样的行为

                    

                     String&operator=(const String &);//实现String t;  t=t2;这样的行为

                    

};



然后我们实现这些接口函数:

int String::num=0;

 

String::String() //自定义构造函数

{

       m_len=strlen("chenyu")+1;

       m_str= new char[m_len];

       strncpy(m_str,"chenyu",m_len);

       num++;

}

 

String::~String() //析够函数

{

       num--;

       cout<<"destory"<<m_str<< " left:" << num<< endl;

       delete[] m_str;

      

}

                    

ostream &operator<<(ostream&os,String &str) //重载<<

{

       os<<"str.m_len:"<<str.m_len<<endl

        <<"str.m_str:"<<str.m_str<<endl;

        

       returnos;

 

}

 

String::String(const String &str) //拷贝函数                        

{     m_len=str.m_len;

       m_str=newchar[m_len];

       strncpy(m_str,str.m_str,m_len);

       num++;

      

}

 

String::String(const char *str) //类型转换构造函数,

 {

       m_len=strlen(str)+1;

       m_str=new char [m_len];

       strncpy(m_str,str,m_len);

       num++;

}

 

 

String &String::operator=(const char*str)//赋值重载,

{

 

       if(NULL==str)

       {

              cout<<"=err"<<endl;

              return(*this);

       }

      

       deletem_str;

      

       m_len=strlen(str)+1;

       m_str= new char[m_len];

       strncpy(m_str,str,m_len);

      

       return(*this);

}

 

String &String::operator=(const String&str)  //赋值重载,

 {

 

 

if(&str==this)       //这里要加一个入口检查,如果出现 string t1; t1=t1 ;这样的行为,会把t1的 m_str 给delete ,后面的赋值就会出现问题

       {

              return(*this);

      

       }

       deletem_str;

       m_len=str.m_len;

       m_str= new char[m_len];

       strncpy(m_str,str.m_str,m_len);

      

       return(*this);

 

}

 

 

 

然后下面调用函数(张老师说的专业用语,^_^):

 

int main()

{

       Stringstr1;

       cout<<"str1:"<<str1<<endl;

      

       Stringstr2(str1);   //等价于String str2=str1;

       cout<<"str2:"<<str2<<endl;

      

 

       Stringstr3=str1;   //等价于String str3(str1); 这个不需要对=重载 是初始化

       cout<<"str3:"<<str3<<endl;

      

       Stringstr4 = "huhu";     //  等价于String str4("huhu");

       cout<<"str4:"<<str4<<endl;

      

       Stringstr5("huhu");              //  等价于String str5="huhu";

       cout<<"str5:"<<str5<<endl;

      

      

       Stringstr6;

       cout<<"str6:"<<str6<<endl;

      

       str6="xiejing";      

       cout<<"str6:"<<str6<<endl;

      

      

       Stringstr7;  

       str7=str6;        //这个要对=重载  是赋值

       cout<<"str7:"<<str7<<endl;

      

      

       Stringstr8("xixihaha");

       cout<<"str8:"<<str8<<endl;

      

       Stringstr9;

       cout<<"str9:"<<str9<<endl;

      

       str8=str8;

      

       cout<<"str8:"<<str8<<endl;

      

       return0;

}

 

从对这个简单程序的编写,遇到了一些问题,就是一些定义方式的理解。

 

1.对于上面的类String ,我们可以定义一个对象str1,如:

String str1;

输出:

       cout<<"str1:"<<str1<<endl;

可以看到里面预定义构造函数对其的初始化内容。

 

2.我们还可这样定义:

String str2(str1);  

这种定义实质上是等价于Stringstr2=str1;的,在这里我们就要调用拷贝构造函数了,大家都知道如果我们不自己定义拷贝构造函数,系统会调用默认拷贝构造函数,默认拷贝构造函数是一种浅拷贝,是一种值到值的复制,没有牵扯到空间的分配。可是在这个程序中,在我们的对象里,我定义了一个指针,在定义对象的时候系统会用new给每个对象分配空间,对于Stringstr2(str1);这个语句来说,如果按照系统的浅拷贝方式的话,str1和str2的m_str指针都会指向同一个存储空间,如下图:(这里图贴补上去,好理解)

 

好了,下面在说一个问题,当一个对象的生命周期结束之后,系统会调用析构函数去做一些处理,对于String str2=str1,我定义了一个析构函数,里面有一个delete,它使对象放弃对new分配的空间的使用权。当这两个对象的生命周期结束之后,会调用这个析构函数,对于str1和str2来说,它们的m_str指向同一个存储空间,这样结束后,会对这个存储空间delete两次,所以会出错。那么如何处理String str2=str1呢?对于前面的这个问题,我们可以给str2分配一个独立的空间,这样当析构时,就不会出错了,即定义个深拷贝构造函数:

 

String::String(const String &str) //拷贝函数 

  { 

m_len=str.m_len;

       m_str=newchar[m_len];

       strncpy(m_str,str.m_str,m_len);

       num++;

      

}

 

定义的时候,还要注意,参数的const关键字不能省略,不然会出错的。

 

 

 

3. 对于这种形式,我们可以做一下对比,

(1)      Stringstr2=str1

(2)      String str2str2=str1

这两种表达意义是不一样的对于(1)来说,我们要调用深拷贝函数,但对于(2)来说,我们要调用对“=”的重载。

即代码中的:

String str7;  

       str7=str6;       

 

对“=”的重载

String&String::operator=(const String &str)

 {

 

 

if(&str==this)       //这里要加一个入口检查,如果出现 string t1; t1=t1 ;这样的行//为,会把t1的 m_str 给delete

    {

        return (*this);

   

    }

    delete m_str;

    m_len=str.m_len;

    m_str = new char[m_len];

    strncpy(m_str,str.m_str,m_len);

   

    return (*this);

 

}

 

4. 在代码中可以看到,还有这种形式:

String str4 ="huhu";  

它等价于Stringstr4("huhu");

 

这相当于一种类型的转换,即先把“huhu”转换为一个临时对象,然后再赋值给str4,这样的话我们要调用类型转换构造函数,即:

String::String(constchar *str) //类型转换构造函数,

 {

    m_len=strlen(str)+1;

    m_str= new char [m_len];

    strncpy(m_str,str,m_len);

    num++;

}

   

 

5、在代码中还可以看到这种形式:

String str6;

str6="xiejing";

 

我们再和上面的对比下:

(1)

String str6;

str6="xiejing";

 

(2)String str4 = "huhu";

对于(2)来说,这样使用,它调用的是类型转换函数,但对于(1)来说就不是了,它调用的是:对“=”的重载函数

String&String::operator=(const char *str)//赋值重载,

 {

 

    if(NULL==str)

    {

        cout<<"=err"<<endl;

        return (*this);

    }

   

    delete m_str;

   

    m_len=strlen(str)+1;

    m_str = new char[m_len];

    strncpy(m_str,str,m_len);

   

    return (*this);

}

 

 

总结起来就是一下四种形式,对于不同的情况,要调用不同的函数:

string str1;

 

(1)string str2=str1;  //--àstringstr2(str1)

 

(2)stringstr3;

str3=str1;

 

(3)stringstr4=”huhuhu”; //--àstring str4(“huhuhu”)

 

(4)stringstr5;

   str5=”huhuhu”;

 

 本人菜鸟级别的,哪里不对的地方,欢迎拍砖。。。。。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值