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