簡體   English   中英

無法初始化“std::string&”類型的引用(非 const 限定)

[英]a reference of type “std::string&” (not const-qualified) cannot be initialized

當我嘗試編譯以下 function 時出現錯誤。

string& foo(){
return "Hello World";
}


Error:
1   IntelliSense: a reference of type "std::string &" (not const-qualified) cannot be initialized with a value of type "const char [12]"

您的代碼有兩個問題。 首先, "Hello World!" char const[13] ,而不是std::string 因此編譯器必須(隱式)將其轉換為std::string 轉換的結果是一個臨時的(C++ 中的右值),並且您不能使用臨時初始化對非常量的引用。 第二個是即使你可以(或者你聲明了 function 以返回對 const 的引用),你返回的引用將立即從 Z31A1FD140BE4BEF2D11E121EC9A18A 中取出 go (因此被破壞)5; 對結果引用的任何使用都將導致未定義的行為。

真正的問題是:為什么要引用? 除非您實際上指的是 object 中具有更長生命周期的東西,目的是客戶端代碼修改它(通常不是一個好主意,但有明顯的例外,例如矢量的operator[] ),您應該返回按價值。

“Hello World”不是一個字符串,它是一個字符數組。 c++ 編譯器需要將其轉換為字符串值,而不是字符串引用(因為它不是字符串),因此您的 function 應如下所示:

string foo(){
    return "Hello World";
}

要擴展(應 OP 的要求),編譯器會執行以下操作:

string foo(){
    char a[] = "Hello World";
    string s( a ); 
    return s;
}

值 s 由 std::string 復制構造函數從 function 中復制出來。

您正在指示編譯器返回從 char 數組“Hello World”創建的臨時 std::string。 它需要把它放在某個地方,並有人負責清理它。 您可以通過以下幾種方式做到這一點:

  • 返回一個 auto_ptr
  • 返回一個字符串 object
  • 返回對字符串 object 的 const 引用(盡管這確實給我留下了誰清理它的問題?)
  • (僅限 c++0x)返回對 std::string 的右手引用。 (std::string &&)

第二個可能是最簡單的。 編譯器將使用 RVO(返回值優化)來刪除由它調用的副本。

就這樣做吧。

const string foo() {
    return string("Hello World");
}

我想你想要:

string foo(){
    return "Hello World";
}

仔細聽


要了解該問題及其解決方案,您必須了解編譯器的一些工作原理。 但是,別擔心,我會解釋並盡可能保持簡單。

字符串& foo()字符串 foo()

在第一個示例中,我們希望將“引用”返回給已創建的字符串,該字符串應具有 memory 地址(我的意思是左值)。 如果我們返回,像這樣:

string& foo()
{
     return "Example String";
}

它永遠不會起作用,因為你可能已經找到了原因。 字符串:“示例字符串”是一個臨時值,沒有 memory 地址,因為它尚未構造。 它必須在任何字符串變量內部的某個地方構造,在那里它將被分配給 memory 地址。 目前,它沒有 memory 地址(我的意思是右值)。

同樣,在第二種情況下,如果我們這樣做:

string foo()
{
     return "Example String";
}

在這里,我們實際上是在構造一個 String 類型的新變量,從那里調用它。 例如,如果我們這樣做:

int main()
{
     string Test = foo();
}

將在等式運算符的右側創建一個字符串變量,並將數據復制到測試變量(如果禁用編譯器優化)。 但是等等,還有別的東西。

什么是: const string& foo()


這里有一些編譯器的魔法。 不讓事情變得復雜:),我只想說,它也有string& foo()string foo()的特性,還有一些額外的特性。

這意味着如果我們這樣做:

const string& foo()
{
    string Test = "Example String";
    return Test;
}

這會將(常量)“引用”返回到字符串 Test。 這很明顯。 但是,如果我們這樣做:

const string& foo()
{
    return "Example String";
}

編譯器將為“示例字符串”智能地創建一個臨時寄存器(在匯編中)並將其存儲在那里。 然后,它將返回對該寄存器的引用。 這個 Register 事情只發生在 const Reference 的情況下。

結論


使用const string& foo()來解決您的問題,您可能知道我們這樣做的原因:)。 如果您想了解更多信息,請查看 C++ 中的類型系統主題。 快樂學習。

暫無
暫無

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

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