2个小时没有搞定!!!拷贝构造函数极为奇怪的问题,大虾们一定帮忙。

eaglezhao 2004-03-23 10:44:48
我在学习操作符重载和拷贝构造函数时出现了奇怪的问题,给出大家代码(有点长),希望高手能够解决。
/*
String.h 头文件
*/
class String
{
private:
char *str;
public:
String();
String(const char *str);
String(const String &s);
virtual ~String();

String operator +(const String &s);
String& operator =(const String &s);

char * c_str();
};

/*
String.cpp
*/

#include "String.h"
#include <string.h>
#include <iostream.h>

String::String()
{
str=new char[1];
strcpy(str,"\0");
cout<<"constructor:\t"<<this<<endl;
}

String::~String()
{
cout<<"destructor:"<<this<<endl;
delete str;
}

String::String(const char *str)
{
cout<<"param constructor:"<<this<<endl;
int len=strlen(str);
this->str = new char[len+1];
strcpy(this->str,str);
}

String::String(const String &s)
{
str=new char[strlen(s.str)+1];
strcpy(str,s.str);
cout<<"copy constructor:"<<this<<endl;
}

String &String::operator =(const String &s)
{
cout<<"Assign opertor:"<<this<<endl;
delete str;
str=new char[strlen(s.str)+1];
strcpy(str,s.str);
return (*this);
}

char * String::c_str()
{
return str;
}

String String::operator +(const String &s)
{
/* 此段代码在最后一句会调用拷贝构造函数,并且会导致错误
String tmp(str);
strcat(tmp.str,s.str);
return tmp;
*/

/* 此段代码不会调用拷贝构造函数,而且不会出错*/
char *temp=new char[strlen(str)+1];
strcpy(temp,str);
strcat(temp,s.str);
return String(temp);
}

/*
mainfile.cpp
*/
#include "String.h"
#include <iostream.h>

int main(int argc,char* argv[])
{

String s1("hello");
String s2(" world");
String s3;
s3=s1+s2; //注意:在这里出现错误。
cout<<s3.c_str()<<endl;
return 0;
}

...全文
84 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
eaglezhao 2004-03-23
  • 打赏
  • 举报
回复
为什么不可以结贴?

老是给提示说:跟进贴数大于结贴数。
angelo23 2004-03-23
  • 打赏
  • 举报
回复
确实是的,我刚才试过了:用vc++6.0默认做这个优化(debug模式),用g++3.2.0默认不作优化(就是说即便return String(temp)仍然会调用copy constructor)但打开优化选项就不会调用了
Quain 2004-03-23
  • 打赏
  • 举报
回复
angelo23(angelo)
“编译器对return String(temp);这里做了优化,省去了调用copy constructor的步骤”

这样也可以??
eaglezhao 2004-03-23
  • 打赏
  • 举报
回复
高手九就是高手,原来是strcat的问题。多谢!!结账
北极猩猩 2004-03-23
  • 打赏
  • 举报
回复
析构函数中应该用delete[] str
strcat不会增加内存空间,所以一定要为目标字符串预先分配足够的内存空间才行。
而你得tmp只是分配了正好的内存空间,因此在连接之后就出溢出问题了
Quain 2004-03-23
  • 打赏
  • 举报
回复
之所以会调用拷贝构造函数,请看你的重载+函数
String String::operator +(const String &s)
这里返回的是一个string而不是一个string的引用,也就是说,你这个函数重新用拷贝函数构造了一个新的string类然后用=操作符赋给了s3,所以这里会调用用一个拷贝函数。
改正如下String& String::operator +(const String &s)
另外重载函数如下:
strcat(this->str,s.str);
return *this;
楼主再44
sunrui 2004-03-23
  • 打赏
  • 举报
回复
strcat前目标字符串没有分配足够的空间
angelo23 2004-03-23
  • 打赏
  • 举报
回复
程序的错误即如oo和xstring所述。至于
/* 此段代码不会调用拷贝构造函数,而且不会出错*/
char *temp=new char[strlen(str)+1];
strcpy(temp,str);
strcat(temp,s.str);
return String(temp);
我的想法是编译器对return String(temp);这里做了优化,省去了调用copy constructor的步骤。如果你写的是String st(temp); return st;那仍然会调用copy constructor
sdhls 2004-03-23
  • 打赏
  • 举报
回复
俺猜测是与strcat有关
yjh1982 2004-03-23
  • 打赏
  • 举报
回复
是会调用copy construct啊!引起了什么错误?
Jinhao 2004-03-23
  • 打赏
  • 举报
回复

String String::operator +(const String &s)
{
/* 此段代码在最后一句会调用拷贝构造函数,并且会导致错误
String tmp(str);
strcat(tmp.str,s.str);
return tmp;
*/

/* 此段代码不会调用拷贝构造函数,而且不会出错*/
int len1=strlen(str);
int len2=strlen(s.str);
char *temp=new char[len1+len2+1];
strcpy(temp,str);
strcat(temp,s.str);
String ret(temp);
delete []temp;
return ret;
}
oo 2004-03-23
  • 打赏
  • 举报
回复
char *temp=new char[strlen(str)+1]; // new char[strlen(str) + strlen(s.str) +1]才对
strcpy(temp,str);
strcat(temp,s.str);

这里也有内存越界使用,不过后面的程序没把这个问题暴露出来而已。
xstring 2004-03-23
  • 打赏
  • 举报
回复
String String::operator +(const String &s)
{
/* 此段代码在最后一句会调用拷贝构造函数,并且会导致错误
String tmp(str); // 想想调用构造函数时你在构造函数分配多长的内存?
好象长度是str字符串的长度吧,那么下面strcat就要在长度为str字符串长度的内存中存
下长度为str字符串长,加上s字符串长的的东西,里面放的下么?你下面那段代码一样的错
strcat(tmp.str,s.str);
return tmp;
*/

/* 此段代码不会调用拷贝构造函数,而且不会出错*/
char *temp=new char[strlen(str)+1];
strcpy(temp,str);
strcat(temp,s.str);
return String(temp);
}

oo 2004-03-23
  • 打赏
  • 举报
回复
String tmp(str);
strcat(tmp.str,s.str);

这里内存越界使用。
MackedNice 2004-03-23
  • 打赏
  • 举报
回复
是编译器优化的原因。
return String(temp);
因为编译器生成一个临时的对象(未命名的)
因为函数的返回是按值返回的。
正常的步骤是:
1,生成临时的对象。(构造函数)
2,把临时的对象复制到调用此函数的函数栈,并付给别的对象。
3,析构临时对象。
编译器优化后。把1和3给优化掉了,所以应该调用的是赋值函数。
Quain 2004-03-23
  • 打赏
  • 举报
回复
因为不停有人在顶啊,呵呵
错误是strcat的问题,但是你问的问题为什么会出现拷贝构造函数则是我说的原因
101monster 2004-03-23
  • 打赏
  • 举报
回复
呵呵,UP!
langzi8818 2004-03-23
  • 打赏
  • 举报
回复
。。。。。。。。。。

64,682

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧