簡體   English   中英

C ++:“我的文本”是std :: string,* char還是c-string?

[英]C++: Is “my text” a std::string, a *char or a c-string?

我剛剛做了一個看似常見的新手錯誤

首先,我們閱讀了許多教程之一,如下所示:

 #include <fstream>
 int main() {
      using namespace std;
      ifstream inf("file.txt");
      // (...)
 }  

其次,我們嘗試在代碼中使用類似的東西,如下所示:

#include <fstream>
int main() {
    using namespace std;
    std::string file = "file.txt"; // Or get the name of the file 
                                   // from a function that returns std::string.
    ifstream inf(file);
    // (...)
}

第三,新手開發人員對一些神秘的編譯器錯誤消息感到困惑。

問題是ifstreamconst * char作為構造函數參數。

解決方案將std :: string轉換為const * char

現在,真正的問題是,對於一個新手來說,幾乎所有教程中給出的“file.txt”或類似的例子看起來都像std :: string。

那么,“我的文本”是std :: string,c-string還是* char,還是取決於上下文?

您能否舉例說明“我的文本”將如何根據上下文進行不同的解釋?

[編輯:我認為上面的例子會讓它顯而易見,但我應該更明確一點:我的意思是雙引號中包含的任何字符串的類型,即“myfilename.txt”,而不是單詞的含義'串'。]

謝謝。

那么,“string”是std :: string,c-string還是* char,還是取決於上下文?

  • C和C ++都沒有內置的字符串數據類型,因此代碼中的任何雙引號字符串本質上都是const char * (或者精確的是const char [] )。 “C string”通常是指這個,特別是帶有null終止符的字符數組。
  • 在C ++中, std::string是一個將原始字符串包裝到對象中的便捷類。 通過使用它,您可以避免必須自己執行(雜亂)指針算法和內存重新分配。
  • 大多數標准庫函數仍然只使用char * (或const char * )參數。
  • 您可以將char *隱式轉換為std::string因為后者有一個構造函數來執行此操作。
  • 您必須使用c_str()方法將std::string顯式轉換為const char *

感謝Clark Gaebel指出const ,jalf和GMan提到它實際上是一個數組。

"myString"是一個字符串文字,其類型為const char[9] ,一個9個常量char的數組。 請注意,它有足夠的空間用於null終止符。 所以"Hi"是一個const char[3] ,依此類推。

這幾乎總是正確的,沒有歧義。 但是,必要時, const char[9]將衰減為指向其第一個元素的const char* 並且std::string有一個隱式構造函數,它接受一個const char* 因此,雖然它始終以char數組開頭,但如果需要它,它可以成為其他類型。

請注意,字符串文字具有const char[N]也可以衰減為char*的唯一屬性,但不推薦使用此行為。 如果您嘗試以這種方式修改基礎字符串,則最終會出現未定義的行為。 這不是一個好主意。

std::string file = "file.txt"; 

=的右側包含一個(原始)字符串文字(即一個以空字符結尾的字節字符串)。 它的有效類型是array of const char

=這里是一個棘手的小馬:沒有任務分配。 std::string類有一個構造函數,它將一個指向char的指針作為參數,並調用它來創建一個臨時的std::string ,這用於復制構造(使用std::string的copy ctor) std::string類型的目標file

編譯器可以自由地刪除copy ctor並直接實例化文件。

但是,請注意, std:string與C樣式的以null結尾的字符串不同。 它甚至不需要以空終止。

ifstream inf("file.txt");

std::ifstream類有一個ctor,它接受一個const char * ,傳遞給它的字符串文字衰減到一個指向字符串第一個元素的指針。

要記住的是: std::string從C風格的字符串提供(幾乎無縫)轉換。 您必須查找函數的簽名,以查看是否傳入了const char *std::string (后者是因為隱式轉換)。

那么,“string”是std::string ,c-string還是char* ,還是取決於上下文?

這完全取決於背景。 :-)歡迎使用C ++。

AC字符串是以空字符結尾的字符串,它幾乎總是與char*相同。

根據您使用的平台和框架,“string”這個詞可能有更多含義(例如,它也用於引用Qt中的QString或MFC中的CString )。

C和C ++都沒有內置的字符串數據類型。

當編譯器在編譯過程中發現隱式引用雙引號字符串時(參見下面的代碼),字符串本身存儲在程序代碼/文本中,並生成代碼以創建偶數字符數組:

  • 該數組是在靜態存儲中創建的,因為它必須保留以便稍后引用。
  • 數組是常量,因為它必須始終包含原始數據(Hello)。

所以最后,你有這個常量靜態字符數組的const char *

const char* v()
{
    char* text = “Hello”;
    return text;
    // Above code can be reduced to:
    // return “Hello”;
}

在程序運行期間,當控件找到開括號時,它在堆棧中創建“text”,char *指針,並在靜態存儲區中創建6個元素的常量數組(包括末尾的空終止符'\\ 0')。 當控件找到下一行(char * text =“Hello”;)時,6元素數組的起始地址被分配給“text”。 在下一行(返回文本;)中,它返回“text”。 使用右括號“text”將從堆棧中消失,但是數組仍然在靜態存儲區中。

你不需要使返回類型為const。 但是如果你嘗試使用非常量char *更改靜態數組中的值,它仍會在運行時給出錯誤,因為數組是常量。 因此,確保返回常量總是好的,它不能被非常量指針引用。

但是如果編譯器發現雙引號字符串被明確地稱為數組,則編譯器會假定程序員將(巧妙地)處理它。 請參閱以下錯誤示例:

const char* v()
{
    char text[] = “Hello”;
    return text;
}

在編譯期間,編譯器檢查,引用文本並將其保存在代碼中,以便在欠幅時間內填充生成的數組。 此外,它計算數組大小,在這種情況下再次為6。

在程序運行期間,使用open括號,在堆棧中創建具有6個元素的數組“text []”。 但沒有初始化。 當代碼找到(char text [] =“Hello”;)時,數組被初始化(使用編譯代碼中的文本)。 所以數組現在在堆棧上。 當編譯器找到(return text;)時,它返回數組“text”的起始地址。 當編譯器找到結束括號時,數組將從堆棧中消失。 因此無法通過返回指針引用它。

大多數標准庫函數仍然只使用char *(或const char *)參數。

標准C ++庫有一個強大的類,稱為字符串,用於處理文本。 字符串的內部數據結構是字符數組。 標准C ++字符串類旨在處理(並隱藏)以前C程序員所需的字符數組的所有低級操作。 請注意,std :: string是一個類:

  • 您可以將char *隱式轉換為std :: string,因為后者有一個構造函數來執行此操作。
  • 您可以使用c_str()方法將std :: string顯式轉換為const char *。

C ++標准庫提供了一個std :: string類來管理和表示字符序列。 它封裝了內存管理,大部分時間都是作為C字符串實現的; 但這是一個實施細節。 它還為常見任務提供操作例程。

std :: string類型將始終是(它沒有char *的轉換運算符,這就是你有c_str()方法的原因),但它可以被C字符串初始化或分配(的char *)。

另一方面,如果你有一個函數將std :: string或const std :: string&作為參數,你可以將一個c-string(char *)傳遞給該函數,編譯器將構造一個std: :為你原生地字符串。 根據你提出的背景,這將是一個不同的解釋。

它應該盡可能多地意味着std::string (或替代方法,如wxStringQString等,如果你使用的是提供這樣的框架。有時你沒有真正的選擇,只能使用NUL終止的字節序列,但你通常希望盡可能避免它。

最終,根本就沒有明確,明確的術語。 這就是人生。

要使用正確的措辭(如C ++語言標准中所示), 字符串是第21.3節“字符串類”(如C ++ 0x N3092中)中std :: basic_string(包括std :: string)的變種之一,而ifstream的構造函數的參數是NTBS (空終止的字節序列)

引用,C ++ 0x N3092 27.9.1.4/2。

basic_filebuf * open(const char * s,ios_base :: openmode mode);

...

如果可能,打開一個文件,其名稱為NTBS

暫無
暫無

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

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