C++中String类的程序崩溃问题

#include <stdio.h>
#include <iostream>
using namespace std;

class String
{
private:
	char *str;
public:
	String(char *p = NULL)
	{
		if (p != NULL)
		{
			str = new char[strlen(p) + 1];
			strcpy(str,p);
		}
		else
		{
			str = NULL;
		}
	}
	~String()
	{
		delete []str;
	}
	void print() const
	{
		if (str != NULL)
		{
			printf("%s\n",str);
		} 
	}
};
int main()
{
	char ch1[] = "hello world";
	String s1(ch1);
	s1.print();
	return 0;
}


以上,是一个普通的String类,编译运行也不会出现任何错误。
但是,当在main()中再构造一个S2,S1调动系统的拷贝构造函数构造S2时,则出现崩溃。
int main()
{
	char ch1[] = "hello world";
	String s1(ch1);
        String s2(s1);
	s1.print();
        s2.print();
	return 0;
}


这是为什么呢~~~
      
      
首先,我们都知道,当拿一个对象去初始化另一个对象的时候,如果没有自定义的拷贝构造函数,则要调用系统的缺省拷贝构造函数,在String类中,缺省的拷贝构造函数如下


String(const String &s):s(s.str)
        
        
{}


系统缺省的拷贝构造函数是怎么做到拷贝构造的呢?
          
          
待图解:



于是,在main()函数开始后,首先调动构造函数开辟空间构造s1,并且用ch1字符串为其初始化。假如,这片空间的首地址是:0x0065fa82
             
             
那么,当函数构造s2对象的时候,则需要调用系统默认的拷贝构造函数去构造s2,可是,s2str空间却因此与s1相同了有木有!!!任何一个对象的str改变都会造成另一个的
             
             
str也改变的好不好!!!
             
             
然后,main()结束,调用析构函数析构掉s1s2.此时,出问题了,因为两个对象要析构两次,也就是说,要释放两次str空间,可是,明明两个对象的str都指向了同一片空间,这样,就意味着~~~~~~你懂得。于是,就崩溃了。
             
             
这就是传说中的,浅拷贝。
             
             
可以设想一下,假如系统默认的拷贝构造都是这么简单的话,那么当你所定义的任何一个类中,它的数据成员中有指针存在时,你是否会担心发生相同的问题呢。这是很严肃很现实的。
             
             
怎么解决?
             
             
答案就是:自己定义拷贝构造函数。
             
             
当拿一个对象去初始化另一个对象的时候,老老实实的根据所拿对象的指针空间大小来开辟相同大小的空间,是字符串就strcpy()过去,是int等等就挨个赋值过去。
             
             
记着,字符串末尾的'\0'在内存中是要占空间的,但是,strlen()出来的大小,却不包括字符串末尾的'\0'so~~~~开辟空间的时候,你得自己多开一个。
             
             
说的我口干,喝口水去,贴上源码,自己看吧。


class String
{
private:
	char *str;
public:
	String(char *p = NULL)
	{
	     if(p != NULL)
	     {
		str = new char[strlen(p) + 1];
		strcpy(str,p);
	     }
	else 
	{
	     str = new char[1];
	     *str = '\0';
	}
	}
	String(const String &s)
	{
	    if(str != s.str)
	    {
	        str = new char[strlen(s.str) + 1];
		strcpy(str,s.str);
	    }
	}
        ~String()
	{
	    delete []str;
            str = NULL;
	}
	void Print() const
	{
            cout<<str<<endl;
	}
};

























































  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值