【发布时间】:2017-10-18 13:16:54
【问题描述】:
我正在尝试实现一个简单的 GetOrCreate() 方法 - 按键获取一个对象,或者如果不存在则创建一个新对象。到目前为止,没有任何想法。我还希望我的函数的返回值为Status。所以我创建了以下内容:
Status GetOrCreate(KeyType key, ObjectType* object) {
Status s = OK;
decltype(my_map)::iterator iter;
bool inserted_new;
std::tie(iter, inserted_new) = clients_.insert(key, ObjectType(...));
if (inserted_new) {
// s = ... Initialize the new ObjectType ...
}
*object = iter->second;
return s;
}
并调用函数:
ObjectType result(...);
Status s = GetOrCreate(key, &result);
现在,我觉得有点浪费,因为:
-
*object = iter->second;中有不必要的副本 -
ObjectType result(...)中有不必要的对象初始化;
(不确定。我可能错了,或者 c++11 忽略了它们。但我还是想明确知道我在做什么)。
所以我创建了一个版本 #2,它通过 ObjectType** object 代替。我不害怕双指针,但可能需要向我的审阅者解释更多。由于project code-style,*& 不是一个选项。
似乎是一个非常基本的设计问题,但我摸不着头脑。那么,在这里使用双指针是否合理?有更好的方法吗?
我使用的是 C++11(我的大部分经验是 98)。
【问题讨论】:
-
有什么理由不能同时返回包含状态和指针的结构体?
-
(1) 使用
emplace,砍掉中间人。 (2) 为什么不按照UKMonkey所说的去做呢?甚至可能像标准库那样std::pair<Status, ObjectType>。 (3) 顺便说一句,您确定要退回一份吗? -
IMO:关于google.github.io/styleguide/cppguide.html#Reference_Arguments - 尝试改变这条规则 - 很好......也许我不会完全说出我的想法......
-
@EladWeiss - 我宁愿不开始关于优雅的辩论。错误状态很少被正确地遵守......所以无论如何。无论如何,只要返回值被占用,您就没有太多选择。也许是
boost::optional?这样至少调用者不必默认构造Object(一种反模式)。 -
如果您现有的方法样式是返回状态,那么当您想要返回更多信息而不是使用指向调用方存储的指针时,您别无选择,但我会将其添加为第三个参数,即是可选的,并且可以是来自调用者的 NULL。但是,状态返回语义的丢失是发明异常的部分原因。 Emplace 可以帮助您在不构造空或副本的情况下将数据导入地图,但您可能需要使用 piecewise_construct 对复杂性才能在不首先构造地图对象的情况下为地图编制索引。