免责声明:这只是出于好奇而非缺乏其他解决方案!
是否有可能在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;
}
}
这样做可以消除警告并在一定程度上延长临时变量的生命周期,但我认为它仍然容易出错。
背景:
整个事件的触发是由以下访问模式引起的:
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引用时才能正常工作。您不希望将非const引用传递给哨兵值,因为任何人都可以更改它。 - François Andrieuxnew
可以分配内存,但通常会带来更多的伤害而不是帮助。在这种情况下,函数无法知道ptr
是否指向动态分配的内容,并且从同一函数返回拥有/非拥有原始指针的混合是灾难的配方。 - 463035818_is_not_a_numberbegin
和end
成员,这些成员将转发调用到指向的容器或提供一个空范围。在基于范围的 for 循环的上下文中,使用方式基本相同于使用NullOrEmpty
函数。 - François Andrieuxnullptrs
。现在,问题是:默认值(nullptr
的情况)是否会用于除了干净的解引用之外的任何其他方式?如果没有,也许使用boost::filter_iterator
是正确的选择?确实,您会失去范围for循环,但仍然可能值得一试。 - alagner