将 const 引用绑定到右值引用
binding const reference to rvalue reference
我在下面有这个私有成员函数,(class 模板的一部分,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 警告我,我正在 returning 函数 parent_of
中的局部变量或临时(右值)的地址,最后,这种行为是有道理的,因为当控制exists/return 来自 parent_of
的所有局部变量包括函数参数已释放!
现在,当通过值(不是通过 const ref)将函数 parent_of
更改为 return 时,事情开始起作用了!
我来自C++98,(所以我不清楚所有的右值引用)问题是:
我应该何时以及如何使用右值引用 (&&
) 来克服这个问题?我可以引用(包括更改其值)编译器分配的这个临时对象并 return 引用它(用作 return 值)吗?
如果您想根据 returned 表达式的值类别保留 return 值的生命周期语义,您不能 return const&
,甚至是 &&
,因为您将面临悬空引用的问题。
相反,您可以对 return 类型使用 decltype(auto)
,以便推断出 returned 表达式的适当值类别:
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);
}
现在 return 类型将推断出正确的值类别,即左值引用的左值、pr 值(临时值)的右值和 x 值(过期值) ).
return 语句中的转换为 decltype(result)
用于根据 id-expression result
命名的实体类型将表达式转换为适当的类型。
您需要对调用堆栈中要保留生命周期语义的所有函数使用此技术。
您可以将此技术视为完美转发,但方向相反,即向上调用堆栈,而不是向下。
这个答案是基于这个有趣的 lightning talk.
中描述的技术
我在下面有这个私有成员函数,(class 模板的一部分,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 警告我,我正在 returning 函数 parent_of
中的局部变量或临时(右值)的地址,最后,这种行为是有道理的,因为当控制exists/return 来自 parent_of
的所有局部变量包括函数参数已释放!
现在,当通过值(不是通过 const ref)将函数 parent_of
更改为 return 时,事情开始起作用了!
我来自C++98,(所以我不清楚所有的右值引用)问题是:
我应该何时以及如何使用右值引用 (&&
) 来克服这个问题?我可以引用(包括更改其值)编译器分配的这个临时对象并 return 引用它(用作 return 值)吗?
如果您想根据 returned 表达式的值类别保留 return 值的生命周期语义,您不能 return const&
,甚至是 &&
,因为您将面临悬空引用的问题。
相反,您可以对 return 类型使用 decltype(auto)
,以便推断出 returned 表达式的适当值类别:
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);
}
现在 return 类型将推断出正确的值类别,即左值引用的左值、pr 值(临时值)的右值和 x 值(过期值) ).
return 语句中的转换为 decltype(result)
用于根据 id-expression result
命名的实体类型将表达式转换为适当的类型。
您需要对调用堆栈中要保留生命周期语义的所有函数使用此技术。
您可以将此技术视为完美转发,但方向相反,即向上调用堆栈,而不是向下。
这个答案是基于这个有趣的 lightning talk.
中描述的技术