簡體   English   中英

返回對局部變量的引用

[英]Returning reference to a local variable

為什么這段代碼可以在Code::block 中成功運行。 IDB 剛剛報告

警告:“返回對局部變量‘tmp’的引用”,

但成功輸出結果“hello world”。

#include <iostream>
#include<string>
using namespace std;

const string &getString(const string &s)
{
    string tmp = s;
    return tmp;
}

int main()
{
    string a;
    cout<<getString("hello world")<<endl;
    return 0;
}

離開函數后,所有局部變量均被銷毀。 通過返回對tmp的引用,您將返回對一個對象的引用,該對象不久將不復存在(即,從技術上講,其內容不再有意義的內存區域的地址)。

訪問這種懸空的引用會調用所謂的“未定義的行為”,而可悲的是,“照常工作”是一種“未定義的行為”。 這里可能發生的情況是std::string為小字符串(與大字符串相反,它從堆中獲取內存)保留了一個小的靜態緩沖區,並且在離開getString ,此字符串占用的堆棧空間未清零,因此它似乎仍然有效。

如果您嘗試調試構建,或在兩者之間調用另一個函數(這將有效覆蓋堆棧空間),則它將不再起作用。

您正在引起不確定的行為。 該標准無法說明在這種情況下會發生什么,但是編譯器已檢測到它。

getString返回的那一刻, tmp消失了。 使用返回的引用是未定義的行為,因此任何事情都可能發生。

要修復您的代碼,請按值返回字符串:

string getString(const string &s)
{
...

也許此鏈接會為您提供幫助。

你確定嗎? 它應該是段錯誤的(在大多數平台上,它將與gcc一起使用)。 該代碼確實包含一個錯誤,如果您“幸運”並且可以正常工作,那么您就在地毯下刷了一個討厭的錯誤。

您的字符串是通過引用返回的,也就是說,不是生成一個在您要返回的上下文中有效的新字符串,而是返回了一個指向過期,已破壞的對象的指針,這很糟糕。 const string getString...將用作函數返回類型的聲明。

臨時對象被釋放,但是它的內容仍然存在於堆棧中,直到有人重寫它為止。 嘗試在調用函數和輸出返回的對象之間調用一些函數:

const string& garbage = getString("Hello World!");
callSomeFunctionThatUsesALotOfStackMemory();
cout<< garbage << endl;

C ++標准告訴我們,將臨時對象綁定到const引用可以將臨時對象的生存期延長到引用本身的生存期。 因此,該代碼應可在任何符合標准的編譯器上工作,但在我看來,這種做法本身並不是很好。

如果您確實使用示例中當前未使用的字符串作為字符串a = getString(“ Hello World!”),則只需復制一個副本,如果使用const string&a = getString(“ Hello World!”),我敢打賭您永遠不應該浪費您的臨時工。

如您所見,通過調用goodByeString()可以稍微修改以下示例代碼。 就像其他答案一樣,getString中名為tmp的變量是本地變量。 函數返回后,變量將超出范圍。 由於是堆棧分配的,因此函數返回時,內存仍然有效,但是一旦堆棧再次增長,tmp所在的內存部分就會被其他內容重寫。 然后對a的引用包含垃圾。

但是,如果您決定輸出b,因為它沒有被引用返回,則內容仍然有效。

#include <iostream>
#include<string>
using namespace std;

const string &getString(const string &s)
{
  string tmp = s;
  return tmp;
}

string goodByeString(const string &s)
{
  string tmp = "lala";
  tmp += s;
  return tmp;
}

int main()
{
   const string &a = getString("Hello World!\n");
   string b = goodByeString("ciao\n");
   cout << a << endl;
   return 0;
}

暫無
暫無

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

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