[英]Member Variables and Functions through this pointers
#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(commented),並希望輸出為
Hello Hello Java Hello
通過this
指針對Data成員進行深層復制。
如何將Hello字符串更改為Java
由於String
類內的錯誤,您的String
類不能用於在其上構建程序。 您必須先解決這些錯誤,然后再考慮將String
用作字符串類。
因此,此答案解決了如何首先修復String
-從那里開始,您現在就可以編寫程序,知道您沒有在錯誤的基礎上工作。
錯誤1:默認構造
當默認構造一個String
時,您無法初始化sptr
。 因此,當執行~String()
,對delete
的調用將嘗試delete
未初始化的指針。
簡單的1行main
功能,例如:
int main()
{
String s;
} // <-- destructor of s may crash
如本例所示,將顯示未定義的行為並可能崩潰。
要解決此問題:
class String
{
public:
String() : sptr(nullptr) {}
//...
};
現在,當在sptr
上發出delete []
時,不會有任何危害,因為delete []
nullptr
是完全有效的(基本上是無操作)。
錯誤2:分配運算符有誤
您的String::operator=
無法取消分配先前分配的內存。 另外,由於&other
始終為true
,因此對NULL
的檢查是不正確的。
我假設這是對自我分配的檢查,但是書寫不正確。 通過將當前對象( this
)的地址與傳入的對象的地址進行比較來完成自我分配檢查:
if (this != &other)
一旦有了,就可以用這種方式編寫其余功能:
if(this != &other)
{
String tmp( other );
std::swap(tmp.sptr, sptr);
}
return *this;
此功能所做的全部工作就是將other
副本復制到名為tmp
的臨時String
,用tmp.sptr
換出sptr
,然后讓tmp
與舊數據一起消失。 這稱為復制/交換慣用法 ,您只是在其中將當前對象的內容與臨時對象的內容交換出去,並讓臨時對象與舊內容一起消失。
請注意,在使用復制/交換時,無需進行自我分配檢查,但是進行此項檢查沒有任何危害(當存在自我分配檢查時,甚至可以做一個很小的優化)。
編輯:另一個問題是operator=
應該返回對當前對象的引用,而不是全新的String
對象。 簽名應為:
String& operator=( const String& other ) // <-- note the return type is String&
{
//... code
//...
return *this;
}
錯誤3:錯誤的delete
形式
由於您是使用new []
分配的,因此您應該使用delete []
,而不僅僅是在析構函數中delete
:
~String()
{
delete [] sptr;
}
鑒於所有這些更改,下面的代碼不再有問題,如此處的Live Example所示。
現在您有了一個正常工作的String
類,然后可以從那里構建您的應用程序。
對於您的程序,您可以使用賦值運算符輕松更改您的字符串。 不需要change()
函數:
String a2("Hello ");
a2.display();
a2 = "Java ";
a2.display();
由於String::operator=(const String&)
不再因上述更改而出錯,因此現在可以完成分配而不會出現問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.