如果我的类SomeType有一个从地图返回元素的方法(使用键),请说
std::unique_ptr<OtherType> get_othertype(std::string name)
{
return otMap.find(name);
}
这会确保调用者会收到指向地图中指针而不是副本的指针吗?这样做是否可以,或者它会尝试调用复制构造函数(并因为它被删除而失败),因为它正在被返回?
假设我必须使用unique_ptr作为我的地图项目。
UPDATE ::
在尝试实现代码之后,似乎unique_ptr和std:map /:pair在gcc 4.4.4中不能一起工作,只是不喜欢unique_ptr作为类型参数。 (见Can't create map of MoveConstructibles)。
我将ptr更改为std :: shared_ptr并且一切正常。
我想我可以在共享指针上使用相同的代码吗?
答案 0 :(得分:12)
unique_ptr
的模型是所有权转移。如果从函数返回unique_ptr
对象,则系统中没有其他unique_ptr
可能引用同一对象。
这就是你想要的吗?我非常怀疑它。当然,你可以简单地返回一个原始指针:
OtherType* get_othertype(const std::string& name)
{
return otMap.find(name)->second.get();
}
因此,客户端可以访问该对象,但地图仍然拥有它。
如果在名称下没有找到条目,上述解决方案相当脆弱。更好的解决方案是在这种情况下抛出异常或返回空指针:
#include <stdexcept>
OtherType* get_othertype(const std::string& name)
{
auto it = otMap.find(name);
if (it == otMap.end()) throw std::invalid_argument("entry not found");
return it->second.get();
}
OtherType* get_othertype(const std::string& name)
{
auto it = otMap.find(name);
return (it == otMap.end()) ? 0 : it->second.get();
}
为了完整起见,这是Anthony提出的返回引用的建议:
OtherType& get_othertype(const std::string& name)
{
auto it = otMap.find(name);
if (it == otMap.end()) throw std::invalid_argument("entry not found");
return *(it->second);
}
以下是如何在地图中返回对unique_ptr
的引用,但是让我们对const进行引用,这样客户端就不会意外地修改原始内容:
unique_ptr<OtherType> const& get_othertype(const std::string& name)
{
auto it = otMap.find(name);
if (it == otMap.end()) throw std::invalid_argument("entry not found");
return it->second;
}
答案 1 :(得分:2)
otMap
的类型是什么?
如果otMap.find(name)
返回std::unique_ptr<OtherType>
作为右值,那么这将正常工作。但是,指向值的所有权现在已转移到返回的指针,因此该值将不再位于映射中。这意味着您使用的是自定义地图类型而不是std::map<>
。
如果你希望能够在地图和中返回一个指向它的指针,那么你需要使用std::shared_ptr<OtherType>
作为地图值类型和返回类型get_othertype()
。
std::map<std::string,std::shared_ptr<OtherType>> otMap;
std::shared_ptr<OtherType> get_othertype(std::string name)
{
auto found=otMap.find(name);
if(found!=otMap.end())
return found->second;
return std::shared_ptr<OtherType>();
}
答案 2 :(得分:0)
otMap.find将返回一个右值,因此如果不是RVO,则会移动该右值。但是,当然,现在你的地图中没有那个特定的对象。另外,我上次检查时,find返回一个迭代器,而不是值类型。
答案 3 :(得分:0)
您是否考虑更改地图以暂停shared_ptr
而不是unique_ptr
?这将使返回值更安全。 unique_ptr
的重点是它是唯一的(即不共享)。