【发布时间】:2021-05-18 13:35:02
【问题描述】:
免责声明:这与其说是缺乏其他解决方案,不如说是出于好奇!
是否可以在 C++ 中实现一个函数:
- 传递了一个 T 类型的指针
- 要么向 T 指向的对象返回类似引用的东西
- 或者,如果指针为空,则返回一个类似引用的东西给默认构造的
T()有一些合理的生命周期?
我们的第一次尝试是:
template<typename T>
T& DefaultIfNullDangling(T* ptr) {
if (!ptr) {
return T(); // xxx warning C4172: returning address of local variable or temporary
} else {
return *ptr;
}
}
第二次尝试是这样的:
template<typename T>
T& DefaultIfNull(T* ptr, T&& callSiteTemp = T()) {
if (!ptr) {
return callSiteTemp;
} else {
return *ptr;
}
}
这消除了临时的警告和somewhat extends the lifetime,但我认为它仍然很容易出错。
背景:
整个事情是由如下所示的访问模式触发的:
if (pThing) {
for (auto& subThing : pThing->subs1) {
// ...
if (subThing.pSubSub) {
for (auto& subSubThing : *(subThing.pSubSub)) {
// ...
}
}
}
}
这可以“简化”为:
for (auto& subThing : DefaultIfNull(pThing).subs1) {
// ...
for (auto& subSubThing : DefaultIfNull(subThing.pSubSub)) {
// ...
}
}
【问题讨论】:
-
您可以返回一个指针,并使用
nullptr。或者,如果您坚持传递类似引用的类型,则可以返回std::optional<std::reference_wrapper<T>>。如果你真的想返回一个引用,你需要某种全局或静态实例来引用。您不能在函数内当场创建实例并返回对它的引用。只有当你返回一个 const 引用时,这才真正有效。您不想将非常量引用传递给标记值,因为任何人都可以更改它。 -
我不做c++,但
new不分配必须删除的内存?这似乎是一种方式 -
使用
const,你可能有一个static const T dummy; return dummy;(没有const,返回的可变实例将被共享:-/所以值将是不可预测的)。 -
一种解决方案是实现一个包含指针的代理范围类型。这种类型将提供
begin和end成员,它们要么将调用转发到指向的容器,要么提供一个空范围。在基于范围的 for 循环的上下文中,用法与使用NullOrEmpty函数基本相同。 -
您的帖子表明您正在迭代一个包含指向容器的指针的容器,并且您想以一种方便的方式跳过
nullptrs。现在,问题是:除了干净的取消引用之外,是否会以任何其他方式使用默认值(nullptr 的情况)?如果没有,也许使用boost::filter_iterator是要走的路?诚然,你失去了远程 for 循环,但它仍然是值得的。
标签: c++ object-lifetime range-based-loop