#include <iostream>
#include<cstring>
using namespace std;
class String
{
private:
char *sptr;
public:
String()
{
}
String(char str[])
{
sptr = new char[strlen(str) + 1];
strcpy( sptr, str );
}
String(const String& source)
{
sptr = new char[strlen(source.sptr) + 1];
strcpy( sptr, source.sptr);
}
~String()
{
delete sptr;
}
String operator=( const String& other )
{
if(&other!=NULL)
{
String tmp( other );
sptr = new char[strlen(tmp.sptr) + 1];
strcpy( sptr, tmp.sptr);
}
return *this;
}
void display()
{
for( char const* p = sptr; *p != '\0'; ++ p) {
std::cout << *p;
}
cout<<endl;
}
};
int main()
{
String a1;
String a2("Hello ");
String a3(a2);
a2.display();
a3.display();
//a2.change("Java ");
a2.display();
a3.display();
}
程序的输出
Hello Hello Hello Hello.
但是我无法在代码中进行以下更改...即,在Main()中,我创建了以下对象
String a1;
String a2("Hello ");
String a3(a2);
a2.display();
a3.display();
//a2.change("Java ");
a2.display();
a3.display();
我想用Java更改对象a2(注释),并希望输出为
Hello Hello Java Hello
通过this
指针对Data成员进行深层复制。
如何将Hello字符串更改为Java
答案 0 :(得分:2)
由于String
类中的错误,不能使用您的String
类来构建程序。您必须先解决这些错误,然后再考虑将String
用作字符串类。
因此,此答案首先解决了如何解决String
的问题-从那里开始,您现在就可以编写程序,知道您没有在错误的基础上工作。
错误1:默认构造
在默认构造sptr
时,您未能初始化String
。因此,当执行~String()
时,对delete
的调用将尝试delete
一个未初始化的指针。
简单的1行main
功能如下:
int main()
{
String s;
} // <-- destructor of s may crash
将显示不确定的行为,并可能崩溃,如this example所示。
要解决此问题:
class String
{
public:
String() : sptr(nullptr) {}
//...
};
现在,在delete []
上发布sptr
时,不会发生伤害,因为delete []
和nullptr
是完全有效的(基本上是无操作)。
错误2:赋值运算符错误
您的String::operator=
无法取消分配先前分配的内存。此外,NULL
的检查不正确,因为&other
将始终为true
。
我假设这是对自我分配的检查,但是书写不正确。通过将当前对象(this
)的地址与传入的对象的地址进行比较来完成自我分配检查:
if (this != &other)
一旦有了,就可以这样编写其余的函数:
if(this != &other)
{
String tmp( other );
std::swap(tmp.sptr, sptr);
}
return *this;
此函数所做的全部工作就是将other
复制到名为String
的临时tmp
中,将sptr
换成tmp.sptr
并让{{1}用旧数据消亡。这就是所谓的copy / swap idiom,在这里您只是将当前对象的内容与临时对象的内容交换出去,而让临时对象与旧内容一起消失。
请注意,使用复制/交换时无需进行自我分配检查,但是进行此项检查没有任何危害(当存在自我分配检查时,甚至可以做一个很小的优化)。
编辑:另一个问题是tmp
应该返回对当前对象的引用,而不是全新的operator=
对象。签名应为:
String
错误3:String& operator=( const String& other ) // <-- note the return type is String&
{
//... code
//...
return *this;
}
的格式错误
由于使用delete
进行分配,因此您应该使用new []
,而不仅仅是析构函数中的delete []
:
delete
鉴于所有这些更改,下面的代码不再有问题,如Live Example here所示。
现在您有了一个有效的~String()
{
delete [] sptr;
}
类,然后可以从那里构建您的应用程序。
对于您的程序,您可以使用赋值运算符轻松更改字符串。不需要String
函数:
change()
由于String a2("Hello ");
a2.display();
a2 = "Java ";
a2.display();
不再存在上述更改的问题,因此现在可以毫无问题地完成分配。