簡體   English   中英

如何在一個類中初始化一個char指針?

[英]how to initialize a char pointer in a class?

我在處理char指針時感到困惑。 請看下面的代碼:

class Person
{
    char* pname;
public:
    Person(char* name)
    {
        //I want to initialize 'pname' with the person's name. So, I am trying to
        //achieve the same with different scenario's

        //Case I:   
        strcpy(pname, name); // As expected, system crash.

        //Case II: 
        // suppose the input is "ABCD",  so trying to create 4+1 char space
        // 1st 4 for holding ABCD and 1 for '\0'.
        pname = (char*) malloc(sizeof(char) * (strlen(name)+1) );
        strcpy(pname, name);

        // Case III: 
        pname = (char*) malloc(sizeof(char));
        strcpy(pname, name);
    }

    void display()
    {
        cout<<pname<<endl;
    }
};

void main()
{
    Person obj("ABCD");
    obj.display(); 
}

對於情況一:如預期的那樣,系統崩潰。

案例二的輸出:

A B C D

案例三的輸出:

A B C D

所以,我不確定為什么案例II和案例III會產生相同的輸出!!!! .....我應該如何在類中初始化char指針?

第三種情況調用了Undefined Behavior ,因此在這種情況下可能會發生任何事情。
在這種情況下,您正在寫的內容超出了分配的內存范圍,這可能會崩潰也可能不會崩潰,但它是UB。

如何在C ++中以正確的方式做到這一點?
通過根本不使用char *
只需使用std :: string即可

請注意, std::string為您提供了c_str()函數,該函數可為您提供基礎字符串。 除非,您不願意將char *所有權傳遞給C風格的api,否則您應始終在c ++中使用std::string

第三個選項也是錯誤的,因為您沒有為其分配足夠的內存。 您正在嘗試將大小為5的字符串復制到大小為1的緩沖區中,這意味着pname[1]之后的數據被錯誤地覆蓋並消失了。

如果幸運的話,您可能會看到諸如內存訪問沖突之類的運行時錯誤,或者您將看不到任何東西,但背后的數據已損壞,例如您的銀行帳戶,直到那時您才知道。

正確的方法是始終分配足夠的內存以進行復制。 正如Als指出的那樣,在C ++中更好的方法是使用std::string ,因為它將使您擺脫對內存的手動管理(分配,增長,釋放等)。

例如,

class Person
{
    std::string pname;
public:
    Person(char* name)
    {
        pname = name;
    }

    void display()
    {
        cout << pname << endl;
    }
};

void main()
{
    Person obj("ABCD");
    obj.display(); 
}

您必須為成員變量pname分配內存,但是,我不知道為什么只能使用string時要使用char*

std::string pname;

//...

pname = std::string(name);

如果有充分的理由為什么必須使用char* ,請執行以下操作:

// initialize the pname
pname = new char[strlen(name)];

// copy the pname
strcpy(pname, name);

之所以不需要在字符串末尾為null終止分配額外的空間,是因為使用雙引號"blah"自動生成一個以null終止的字符串。

如果您從事C ++業務,那么該代表STL字符串轉儲char指針了:

#include <string>

class Person
{
    std::string the_name;
public:
    Person(std::string name) : the_name(name)
    { ...

同樣,cout也被使用。

在案例III中,您執行pname = (char*) malloc(sizeof(char)); ,它為單個char分配足夠的內存。 但是,strcpy無法知道這一點,並且會直接寫入該字節之后的所有內存,直到它完成對傳遞給函數的所有char *的復制為止。 這被稱為緩沖區溢出 ,盡管這可能立即起作用,但可能會破壞某些東西。 如果您只想復制char *的一部分,則可以查看strncpy ,該副本最多復制一定長度(此處有API參考) 如果使用該選項,請確保自己添加以null結尾的字符,因為如果僅復制部分字符串,strncpy將不包括該字符。

pname = (char*) malloc(sizeof(char)); Works是偶然的,對strcpy的調用將寫入尚未分配的內存,因此它可能隨時使您的程序崩潰。

初始化緩沖區的更簡單方法是:

pname = strdup(name);

要么

pname = strndup(name, strlen(name));

參見http://linux.die.net/man/3/strdup

同樣,您必須考慮釋放通過調用free(pname);分配的內存free(pname); 在類析構函數中。

總而言之,所有這些都可以通過使用C ++ std :: string類來避免,這是每個人都提到的。

情況二是對的!

是的,如果我錯了,由於將數據復制到未初始化的指針,它將崩潰。

情況三也是錯誤的,但是現在可以使用,因為您的測試字符串很小! 如果嘗試使用較大的字符串,則將損壞內存,因為您將大型字符串復制到較小的分配空間中。

在某些系統中,malloc適用於群集,因此它通過分配內存塊來工作,而不是逐字節分配。 這意味着,當您使用malloc分配單個字節時(如在案例III中所做的那樣),它會分配更多的空間以達到它可以處理的最小內存塊,這就是為什么您可以向其中移動多於1個字節而不會崩潰的原因系統。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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