我在下面有这个私有成员函数,(是类模板的一部分Heap
):
template <typename Task, typename Priority>
const size_t& Heap<Task, Priority>::parent_of(const size_t& index) const
{
// ** warning C4172: returning address of local variable or temporary
return (this_index-1)/2;
}
我从其他功能调用它,如下所示:
template <typename Task, typename Priority>
void Heap<Task, Priority>::bubble_up(const size_t& start_index)
{
....
if (priority_of(start_index) > priority_of((parent_of(start_index))))
{
... do work ...
//call recursively the bubble_up
bubble_up(parent_of(start_index));
}
...
}
问题是,priority_of
函数参数index
被损坏或在第二次递归调用中释放:
template <typename Task, typename Priority>
const Priority& Heap<Task, Priority>::priority_of(const size_t& index) const
{
return vec.at(index).second;
}
现在,VS警告我,我将在函数中返回局部变量或临时(右值)的地址parent_of
,这在最后是合理的,因为当控件存在/从parent_of
所有局部变量(包括释放的函数参数)返回时,这种行为是有道理的!
现在,当将函数更改为parent_of
按值返回(而不是通过const ref)时,事情就开始起作用了!
我来自C ++ 98,(因此我不太清楚所有右值引用)的问题是:何时以及如何使用右值引用(&&
)来克服这个问题?我可以引用(包括更改其值)编译器分配的该temp对象并返回对其的引用(用作返回值)吗?
如果要根据返回表达式的值类别保留返回值的生存期语义,则不能返回const&
,甚至不能返回a ,&&
因为您将遇到悬挂引用的问题。
相反,您可以将其decltype(auto)
用于返回类型,以便推断出返回表达式的适当值类别:
template <typename Task, typename Priority>
decltype(auto) Heap<Task, Priority>::priority_of(const size_t& index) const
{
decltype(auto) result = vec.at(index).second;
return decltype(result)(result);
}
现在,返回类型将推断出正确的值类别,即,用于l值引用的l值,用于pr值(临时)的r值和x值(过期值)。
演员要decltype(result)
在返回语句用来表达转换为基于由ID表达命名实体的类型选择合适的类型result
。
您需要对要保留生命周期语义的调用堆栈中的所有函数使用此技术。
您可以将这种技术视为完美转发,但是却是相反的方向,即向上调用堆栈而不是向下调用。
该答案基于此有趣的闪电演讲中描述的技术。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句