我想要一个函数返回一个对象的可选引用。想法是避免复制,但似乎我不应该使用根据这个讨论:std::optional specialization for reference types
假设我有一个对象的Map,我希望我的函数返回一个对象的引用,如果它存在于Map中。最好的方法是什么?
struct HeavyObj;
std::map<int, HeavyObj> my_map;
std::optional<HeavyObj&> get_obj(int key){
if(auto it = my_map.find(key); it != my_map.end()){
return std::optional<HeavyObj&>{ ? };
} else {
return {};
}
ps:需要C++17
update,如果我使用指针,我得到:
#include <optional>
#include <map>
struct HeavyObj{
int data;
};
static std::map<int, HeavyObj> my_map;
std::optional<HeavyObj*> get_obj(int key){
if(auto it = my_map.find(key); it != my_map.end()){
return std::optional<HeavyObj*>{&(*it)};
} else {
return {};
}
}
int main(){
auto test = get_obj(3);
return 0;
}
// gcc -std=c++17 -Wall optional.cc -lstdc++
optional.cc: In function ‘std::optional<HeavyObj*> get_obj(int)’:
optional.cc:13:47: error: no matching function for call to ‘std::optional<HeavyObj*>::optional(<brace-enclosed initializer list>)’
13 | return std::optional<HeavyObj*>{&(*it)};
| ^
```
2条答案
按热度按时间wz8daaqr1#
如前所述,您可以使用未初始化的指针为
nullptr
这一事实来模拟optional
行为。然而,有些人可能会认为使用
optional
更干净,因为如果你有一个类似的函数返回optional
int
,那么它会更一致。如果没有找到值,可以使用
std::nullopt
,如果找到了,只需返回值(编译器将执行从HeavyObject* 到可选<HeavyObject*>的转换,但您可以手动执行)。uqxowvwt2#
返回一个
HeavyObj*
,这是惯用的解决方案。C++标准库在许多地方返回充当可选引用的指针。例如:std::get_if(std::variant)
std::any_cast<T*>(std::any*)
这两个都是C++17函数,所以它们绝不是90年代的过时设计。在你的例子中,我们可以使用原始指针如下:
HeavyObj
有一个重载的address-of运算符,我们将使用std::addressof
。*std::optional
问题std::optional<HeavyObj*>
有点问题,因为它在两个方面是可选的:std::optional
可以不保存值,或者HeavyObj*
可以是nullptr
您只需要一个可选层,因此使用
HeavyObj*
。如果你 * 拼命 * 想避免原始指针,那么解决办法是:
但是,这不是很符合人体工程学,因为返回类型是令人难以置信的长。