4

如果我的类 SomeType 有一个从地图返回元素的方法(使用键)说

std::unique_ptr<OtherType> get_othertype(std::string name)
{
   return otMap.find(name);
}

这将确保调用者会收到指向地图中的指针而不是副本的指针?这样做可以吗,还是会尝试调用复制构造函数(并且由于它已被删除而失败),因为它正在被返回?

假设我必须使用 unique_ptr 作为我的地图项。

更新::

在尝试实现代码之后,似乎 unique_ptr 和 std:map/:pair 在 gcc 4.4.4 中不能一起工作,pair 只是不喜欢 unique_ptr 作为类型参数。(请参阅无法创建 MoveConstructibles 的地图)。

我将 ptr 更改为 std::shared_ptr 并且一切正常。

我想我可以对共享指针使用相同的代码吗?

4

4 回答 4

13

的模式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;
}
于 2010-09-23T10:59:49.730 回答
2

是什么类型的otMap

如果otMap.find(name)将 astd::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>();
}
于 2010-09-23T10:59:16.203 回答
0

您会考虑将地图更改为保存shared_ptrs 而不是unique_ptrs 吗?这将使返回值更加安全。的全部意义unique_ptr在于它是独一无二的(即共享)。

于 2010-09-23T21:37:40.880 回答
0

otMap.find 将返回一个右值,因此这个右值将被移动,如果不是 RVO 的话。但是,当然,现在您的地图中没有那个特定的对象。另外,上次我检查时,find 返回一个迭代器,而不是值类型。

于 2010-09-23T10:46:15.423 回答