2010-12-06 100 views
5

我有下面的代碼,其與無警告(-Wall -pedantic)與克++C++傳遞字符串而不是const std :: string&?

#include <iostream> 
#include <string> 

using namespace std; 

class Foo 
{ 
public: 
    Foo(const std::string& s) : str(s) 
    { } 

    void print() 
    { 
     cout << str << endl; 
    } 

private: 
    const std::string& str; 
}; 


class Bar 
{ 
public: 

    void stuff() 
    { 
     Foo o("werd"); 
     o.print(); 
    } 
}; 


int main(int argc, char **argv) 
{ 
    Bar b; 
    b.stuff(); 

    return 0; 
} 

但是當我運行它,只有換行打印出編譯。 發生了什麼事?

如果我做這裏面的東西:

string temp("snoop"); 
Foo f(temp); 
f.print(); 

然後正常工作!

回答

18

這個失敗的原因是因爲它本質上是編譯到下面的內容。

Foo o(std::string("wurd")); 

在這種情況下Foo值正在給構造完成後其被刪除的臨時對象的引用。因此它保持了死亡價值。第二個版本的工作原理是因爲它持有一個比Foo實例具有更長生命週期的本地引用。

要修復此更改,請將記錄從const std::string&更改爲const std::string

+0

歡呼聲,不知道爲什麼我的大腦沒有得到:s – 2010-12-07 01:50:49

2

發生什麼事是引用'str'正在被初始化,以便它指向臨時arg's'。它和使用指針非常相似 - 你指望繼續存在你的構造函數arg,'s'。當臨時被刪除時(在構造函數ftn返回之後),那麼你的引用指向垃圾。

要修復,請更改str以使其實際字符串對象而不是引用。

const std :: string str;

這樣副本將由您的arg字符串組成,並且所述副本將與您的Foo對象具有相同的使用期限。