C++ 将常量引用绑定到右值引用
我在下面有一个私有成员函数(类模板的一部分,C++ 将常量引用绑定到右值引用,c++,rvalue-reference,C++,Rvalue Reference,我在下面有一个私有成员函数(类模板的一部分,Heap): 现在,VS警告我,我正在返回的函数parent\u中的局部变量或临时(rvalue)的地址,这在最后是有意义的,因为当控件存在时/从的parent\u返回所有局部变量,包括函数参数 现在,当将的函数parent_更改为按值返回(而不是按常量ref)时,一切都开始工作了 我来自C++98(因此所有的右值引用对我来说都不清楚),问题是: 何时以及如何使用右值引用(&&&)来克服此问题?我是否可以引用(包括更改其值)编译器分配的这个临时对象并返
Heap
):
现在,VS警告我,我正在返回的函数parent\u中的局部变量或临时(rvalue)的地址,这在最后是有意义的,因为当控件存在时/从
的parent\u返回所有局部变量,包括函数参数
现在,当将
的函数parent_更改为按值返回(而不是按常量ref)时,一切都开始工作了
我来自C++98(因此所有的右值引用对我来说都不清楚),问题是:
何时以及如何使用右值引用(&&&
)来克服此问题?我是否可以引用(包括更改其值)编译器分配的这个临时对象并返回对它的引用(用作返回值)?如果要根据返回表达式的值类别保留返回值的生存期语义,则不能返回常量&
,甚至是&&
,因为您将面临悬空引用的问题
相反,您可以对返回类型使用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);
}
模板
decltype(auto)Heap::优先级(常量大小和索引)常量
{
decltype(auto)result=vec.at(index).second;
返回decltype(result)(result);
}
现在,返回类型将推断出正确的值类别,即l值引用的l值,pr值(临时值)的r值,以及x值(过期值)
return语句中的cast todecltype(result)
用于根据id expressionresult
命名的实体类型将表达式转换为适当的类型
您需要对调用堆栈中要保留生存期语义的所有函数使用此技术
您可以将此技术视为完美的转发,但方向相反,即在调用堆栈上,而不是向下
此答案基于本节中描述的技术。如果您希望根据返回表达式的值类别保留返回值的生存期语义,则不能返回常量&
,甚至不能返回&
,因为您将面临悬空引用的问题
相反,您可以对返回类型使用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);
}
模板
decltype(auto)Heap::优先级(常量大小和索引)常量
{
decltype(auto)result=vec.at(index).second;
返回decltype(result)(result);
}
现在,返回类型将推断出正确的值类别,即l值引用的l值,pr值(临时值)的r值,以及x值(过期值)
return语句中的cast todecltype(result)
用于根据id expressionresult
命名的实体类型将表达式转换为适当的类型
您需要对调用堆栈中要保留生存期语义的所有函数使用此技术
您可以将此技术视为完美的转发,但方向相反,即在调用堆栈上,而不是向下
这个答案基于本节中描述的技术。规则是:从不,从不,从不,通过引用(任何类型的引用)返回函数本地对象。该对象将在函数结束时被销毁,留下一个悬空引用,并使用未定义的行为。通常对您有利-这意味着,如果您构建了大型本地对象,并且所有分支都导致返回该对象,则不会进行复制。它将直接在接收者的“内存”中创建。@aðam多亏了保证的复制省略和NRVO,这通常不是问题。@aðam@aðam如果你有一个复制成本很高的大结构,请为它提供移动语义。搬家应该便宜。(并且,正如其他人指出的,由于NRVO的原因,不会应用任何复制/移动。)规则是:从不,从不,从不,通过引用(任何类型的引用)返回函数本地对象。该对象将在函数结束时被销毁,留下一个悬空引用,并使用未定义的行为。通常对您有利-这意味着,如果您构建了大型本地对象,并且所有分支都导致返回该对象,则不会进行复制。它将直接在接收者的“内存”中创建。@aðam多亏了保证的复制省略和NRVO,这通常不是问题。@aðam@aðam如果你有一个复制成本很高的大结构,请为它提供移动语义。搬家应该便宜。(而且,正如其他人所指出的,由于NRVO,无论如何都不会应用复制/移动。)
template <typename Task, typename Priority>
const Priority& Heap<Task, Priority>::priority_of(const size_t& index) const
{
return vec.at(index).second;
}
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);
}