2014-08-28 51 views
2

這裏是我的代碼:如何返回參考的unique_ptr含nullptr

typedef map<string, unique_ptr<MyClass> > DB; 

const unique_ptr<MyClass>>& find_it(const string &key, const DB &db) 
{ 
    auto itr = db.find(key); 
    if (itr == db.end()) { 
    return nullptr; 
    } 
    return itr->second; 
} 

返回語句使編譯器警告:returning reference to local temporary object [-Wreturn-stack-address].

是的,我可以理解,返回到本地臨時變量的引用是壞了,但我不知道什麼是簡單的解決辦法這裏給出如下:

1. Do not expose the map to the callers of find_it (I use typedef here is just for asking this question, in real code it is wrapped inside an interface). 
2. Using an iterator kind of thing to indicate the position of the searched item is a hassle to me, I like to avoid it. 

鑑於這些,我可以拿出最好的是打破find_it()2復

bool exists(const string &key, const DB &db) 
{ 
    auto itr = db.find(key); 
    return itr != db.end(); 
} 

const unique_ptr<MyClass>>& find_it(const string &key, const DB &db) 
{ 
    auto itr = db.find(key); 
    assert(itr != db.end()); 
    return itr->second; 
} 

有什麼建議嗎?

+4

您不能返回參考'nullptr'你不能在'INT&'參考返回'0'相同的方式。此外,我不明白如何返回迭代器是一件麻煩 - 無論如何你必須解除指針的引用。什麼你應該使用,而不是將返回'提振::可選'(或使用其他'optional'類,也許有自己寫的),如果用戶不應該關心'unique_ptr's(和案件的99%,他不應該 - 它是一個實現細節)。 – milleniumbug 2014-08-28 16:50:27

+2

返回對'unique_ptr'的引用可能被認爲是誤導性的。我認爲返回一個原始指針,或者'shared_ptr'會更好。但是返回一個迭代器對象會比兩者都好。 – 2014-08-28 16:51:32

+0

爲什麼不採取參數迭代器,返回一個迭代器上失敗成功,'db.end()'的位置? – 0x499602D2 2014-08-28 18:15:07

回答

6

return nullptr語句隱含構建unique_ptr<MyClass>實例,你再返回對它的引用,因此警告。一個簡單的解決方法是定義一個staticunique_ptr<MyClass>保持nullptr並返回到一個參考來代替。

const unique_ptr<MyClass>& find_it(const string &key, const DB &db) 
{ 
    static unique_ptr<MyClass> not_found; 

    auto itr = db.find(key); 
    if (itr == db.end()) { 
    return not_found; 
    } 
    return itr->second; 
} 

更好的修復方法可能是使用boost::optional。將返回類型更改爲boost::optional<std::unique_ptr<MyClass>> const&,如果未找到該對象,則返回boost::none

+0

所以我們應該初始化not_found爲nullptr,對嗎? – 2014-08-28 19:24:33

+0

@my_question的[默認構造函數(http://en.cppreference.com/w/cpp/memory/unique_ptr/unique_ptr)會爲你做的。如果你想更明確地說明你在做什麼,你可以用'nullptr'參數來構造它。 – Praetorian 2014-08-28 19:28:49