[英]How to store a const char* to a char*?
我有這個代碼按預期工作:
#define MAX_PARAM_NAME_LEN 32
const char* GetName()
{
return "Test text";
}
int main()
{
char name[MAX_PARAM_NAME_LEN];
strcpy(name, GetName());
cout << "result: " << name << endl;
}
如果我想將結果存儲到char *
(因為我正在使用的框架中的某些函數僅使用char *
作為輸入)而不使用strcpy
(為了代碼的實用性和可讀性,以及學習),怎么可能我做? 保持const
,這很好用:
const char* name;
name = GetName();
但我仍然有const
。
試圖只使用char*
:
char* name;
name = GetName();
我invalid conversion from 'const char*' to 'char*'
。 這種轉換的最佳習慣是什么?
這種轉換的最佳習慣是在整個代碼中使用std::string
。 由於您使用的框架將const char*
作為其輸入,因此您始終可以在std::string
上傳遞c_str()
調用的結果:
std::string GetName() {
return "Test text";
}
int main() {
std::string name = GetName();
int res = external_framework_function(name.c_str());
cout << "result: " << res << " for " << name << endl;
}
遙遠的第二好是在你的代碼中使用const char*
:
const char* name = GetName();
由於您使用的框架采用const char*
您也很好。
如果需要非const指針,則無法復制字符串。 您可以為您創建一個功能,但您仍然有責任釋放您從中獲得的副本:
char* copy(const char* orig) {
char *res = new char[strlen(orig)+1];
strcpy(res, orig);
return res;
}
...
char *name = copy(GetName());
...
delete[] name;
return "Test text";
返回指向只讀字符串文字的指針。
如果您正在使用一個以char*
作為輸入的const char*
,並且您有一個const char*
(例如只讀字符串文字),那么您應該提供從該const char*
開始的字符串的深層副本const char*
這些功能。
否則,如果函數嘗試修改只讀字符串,則會在運行時冒未定義的行為。
你現在擁有的是足夠的; 假設您無法使用std::string
。 (如果您可以使用std::string
並且所有框架函數都使用const char*
輸入,那么我建議您重構代碼以使用std::string
,並傳遞c_str()
方法的輸出那個字符串類到你的框架函數。)
最后,如果你的一些框架函數需要一個char*
那么你總是可以自己構建一個小的適配器類:
class Adapter
{
public:
Adapter(const& Adapter) = delete; /*don't try to copy me please*/
Adapter& operator=(const Adapter& ) = delete; /*don't try to copy me please*/
Adapter(const char* s) : m_s(::strdup(s))
{
}
~Adapter() /*free memory on destruction*/
{
::free(m_s); /*use free to release strdup memory*/
}
operator char*() /*implicit cast to char* */
{
return m_s;
}
private:
char* m_s;
};
然后對於函數void foo(char* c)
,可以調用foo(Adapter("Hello"/*or any const char* */));
和foo
可以隨意嵌入匿名臨時的char*
! 您甚至可以增強此類以將構造函數轉換為char*
,在這種情況下,只會獲取指針的淺表副本(並且析構函數不會刪除內存)。
在C ++中,“刪除const
”的典型方法是使用const_cast<>
:
char *name = const_cast<char*>(GetName());
當然,這是不受歡迎的,丑陋的和潛在的危險,因為GetName()
確實可以返回指向不應該更改的內容的指針,然后你去允許自己更改它。 在這種情況下,這是一個很難找到錯誤的好方法。
解決方法是使用std::string
作為臨時保留區域; 這將意味着復制字符串,但這可能是性能可接受的:
std::string s(GetName());
char *name = s.c_str();
這當然只有在s
超出范圍時不保留name
時才有效。 如果是這種情況,那么您將擁有某種形式的持久性字符串存儲層。
你可以明確地施展它。 (char*) getName()
。 但你可能不應該這樣做。 因為const
位意味着“承諾不改變它”。 所以如果我有一個函數void foo(const char* string)
我正在說:“給我一個指向字符串的指針。我不會改變它。” 如果你聲明一個變量const char* string = "hello";
你是說,不應該改變這個字符串。 因為你做出了這個承諾,編譯器知道,並且可以使你的代碼更有效率。 這就是為什么:
const char* a = "hello";
const char* b = "hello";
(a==b); //is probably true
你的編譯器知道你不會改變a
或b
所以它使它們指向同一個地址,所以它只需要存儲一個"hello"
字符串。 如果你現在要改變a
, b
也會改變,這不是你想要的。
長話短說,如果你絕對確定你的調用函數沒有改變字符串,你可以明確地轉換它。 (或者更好的是,將函數更改為(const char*)
如果它是你的)。
如果你不確定,你將不得不復制。 (就像你已經在使用strcpy()
)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.