C++ C++;字符数组连接
我试图重载加号来连接两个字符串,但是我一直得到一个错误 VS 2010给出了一条断言失败的消息:“表达式:(L“缓冲区太小”&&0)文件:f:\dd\vctools\crt\u bld\self\u x86\crt\src\tcscat\u s.inl行:42 你认为我的代码有什么问题C++ C++;字符数组连接,c++,string,char,assertion,strcat,C++,String,Char,Assertion,Strcat,我试图重载加号来连接两个字符串,但是我一直得到一个错误 VS 2010给出了一条断言失败的消息:“表达式:(L“缓冲区太小”&&0)文件:f:\dd\vctools\crt\u bld\self\u x86\crt\src\tcscat\u s.inl行:42 你认为我的代码有什么问题 #include "stdafx.h" class MyString{ int l; // the length of the array pointed by buf char *buf;
#include "stdafx.h"
class MyString{
int l; // the length of the array pointed by buf
char *buf; //pointer to a char array
public:
...
MyString(char *);
friend MyString operator+(MyString &,MyString &);
...
};
MyString::MyString(char *p)
{
buf=new char[strlen(p)+1];
strcpy_s(buf,strlen(p)+1,p);
l=strlen(p)+1;
}
MyString operator+(const MyString &a,const MyString &b)
{
MyString result("");
result.l=a.l+b.l;
delete[] result.buf;
result.buf=new char[result.l+1];
result.buf[0]='\0';
strcat_s(result.buf,result.l+1,a.buf);
strcat_s(result.buf,result.l+1,b.buf);
return result;
}
int _tmain(int argc, _TCHAR* argv[])
{
MyString a("hello"),b("world"),c("");
c=a+b;
system("pause");
return 0;
}
现在可以了!谢谢大家 应该是
result.buf=newchar[result.l+1]
允许空字符。它应该是result.buf=新字符[result.l+1]
允许空字符。在运算符+中,变量“MyString result”在堆栈上声明,随后通过引用返回,这是错误的
然后编辑了这篇文章。变量“result”不再在堆栈上声明,而是在堆上分配。然而,随后出现了内存泄漏
这里正确的做法是按值返回,并在堆栈上声明“MyString result”。还要确保您有一个复制构造函数。还有一个破坏者
您还应该使构造函数在运算符+中使用“const char*”变量“MyString result”在堆栈上声明,随后通过引用返回,这是错误的
然后编辑了这篇文章。变量“result”不再在堆栈上声明,而是在堆上分配。然而,随后出现了内存泄漏
这里正确的做法是按值返回,并在堆栈上声明“MyString result”。还要确保您有一个复制构造函数。还有一个破坏者
您还应该使构造函数接受“const char*”
strcat_s
的第二个参数是目标缓冲区的大小,而不是应附加的字符串的大小。
所以你需要把它改成
strcat_s(result->buf,result->l+1,a.buf);
strcat_s(result->buf,result->l+1,b.buf);
operator+实现的其余部分也被破坏,其他人已经注意到了这一点。新建一个实例,然后按值返回它是毫无意义的。只需在堆栈上实例化结果并按值返回即可
strcat_s
的第二个参数是目标缓冲区的大小,而不是应附加的字符串的大小。
所以你需要把它改成
strcat_s(result->buf,result->l+1,a.buf);
strcat_s(result->buf,result->l+1,b.buf);
operator+实现的其余部分也被破坏,其他人已经注意到了这一点。新建一个实例,然后按值返回它是毫无意义的。只需在堆栈上实例化结果并按值返回。这将给出相同的断言失败消息;我认为a.buf结尾的“\0”被b.buf中的第一个字符替换,它给出了相同的断言失败消息;我以为a.buf结尾的“\0”已被b.bufw中的第一个字符替换。为什么要将result.buf中的第一个字符设置为空字符?strcat可能认为这是缓冲区的结尾。因为strcat在字符串的结尾处连接到它找到的“\0”。此问题已编辑,以便包括接受答案提出的修复。这使得答案有点毫无意义。这对未来的读者有什么用处呢?问题还包括以前版本的代码。。。点击“8小时前编辑”。现在它工作了,让我建议一个优化。版本1:添加一个(可能是私有的)接受两个字符串并将它们连接起来的构造函数,然后在操作符+(有效地将连接代码移动到构造函数)中使用该构造函数。版本2:添加一个不初始化对象的(私有)构造函数,并在运算符+(将串联代码保留在运算符+)中使用它。-这样你就可以安全地进行一次新的、一次删除和一次对strcpy_的调用。同时移动
l=strlen(p)+1
在其他两次调用之前先调用char*
ctor,然后在接下来的两行中使用l
而不是strlen
。为什么要将result.buf中的第一个char设置为空字符?strcat可能认为这是缓冲区的结尾。因为strcat在字符串的结尾处连接到它找到的“\0”。此问题已编辑,以便包括接受答案提出的修复。这使得答案有点毫无意义。这对未来的读者有什么用处呢?问题还包括以前版本的代码。。。点击“8小时前编辑”。现在它工作了,让我建议一个优化。版本1:添加一个(可能是私有的)接受两个字符串并将它们连接起来的构造函数,然后在操作符+(有效地将连接代码移动到构造函数)中使用该构造函数。版本2:添加一个不初始化对象的(私有)构造函数,并在运算符+(将串联代码保留在运算符+)中使用它。-这样你就可以安全地进行一次新的、一次删除和一次对strcpy_的调用。同时移动l=strlen(p)+1代码>在其他两次调用之前先调用char*
ctor,然后在接下来的两行中使用l
而不是strlen
。你所说的非常有趣,这就是我要做的,但是你知道strcat_(result->buf,strlen(a.buf),a.buf)有什么问题吗代码>?你说的很有趣,我也会这么做,但是你知道strcat_s(result->buf,strlen(a.buf),a.buf)有什么问题吗代码>?