2014-08-28 56 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