簡體   English   中英

通過此指針的成員變量和函數

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM