如果std :: max()通过引用返回(必须这样做),是否可能导致悬挂的引用? [英] If std::max() returns by reference (as it must), might that lead to a dangling reference?
问题描述
考虑范式 max
模板函数, std :: max()
:
// From the STL
// TEMPLATE FUNCTION _Debug_lt
template<class _Ty1, class _Ty2> inline
bool _Debug_lt(const _Ty1& _Left, const _Ty2& _Right,
_Dbfile_t _File, _Dbline_t _Line)
{ // test if _Left < _Right and operator< is strict weak ordering
if (!(_Left < _Right))
return (false);
else if (_Right < _Left)
_DEBUG_ERROR2("invalid operator<", _File, _Line);
return (true);
}
// intermediate #defines/templates skipped
// TEMPLATE FUNCTION max
template<class _Ty> inline
const _Ty& (max)(const _Ty& _Left, const _Ty& _Right)
{ // return larger of _Left and _Right
return (_DEBUG_LT(_Left, _Right) ? _Right : _Left);
}
...或者,以更简单的形式:
... Or, in simpler form:
template<typename T> inline
T const & max(T const & lhs, T const & rhs)
{
return lhs < rhs ? rhs : lhs;
}
我理解为什么 max
模板必须按引用返回(以避免昂贵的副本并避免需要复制构造函数)。
I understand why the max
template must return by reference (to avoid expensive copies and to avoid the requirement for a copy constructor).
但是,这不会导致出现悬挂的可能性
However, doesn't this lead to the possibility of dangling references, as in the following code?
int main()
{
const int & max_ = ::max(3, 4);
int m = max_; // Is max_ a dangling reference?
}
在这种情况下,代码可以正常构建和运行(VS 2010),并且值 m
设置为4。但是,令我惊讶的是,由于硬编码的右值, max _
是一个悬挂的引用。 3
和 4
直接传递给 max
,为这些硬编码的右值常量分配的存储空间可以在到达以下代码行时正确地取消分配。
In this case, the code builds and runs fine (VS 2010) and the value m
is set to 4. However, it strikes me that max_
is a dangling reference since the hard-coded rvalues 3
and 4
were passed directly to max
, and the storage allocated for these hard-coded rvalue constants can rightfully be de-allocated by the time the following line of code is reached.
我可以预见类似的边缘情况类对象,例如
I could envision analogous edge-cases for full-fledged objects, such as
class A
{
friend bool operator<(A const &, A const &)
{
return false;
}
};
int main()
{
const A & a_ = ::max(A(), A());
A a = a_; // Is a_ a dangling reference?
}
我纠正了 max的用法
(在调用参数列表中定义的右值作为参数传递)是使用 max
的潜在陷阱的一个示例,由于需要定义 max
以返回引用,以避免昂贵的副本(并避免使用副本构造函数)?
Am I correct that this usage of max
- in which rvalues defined within the call argument list are passed as arguments - is an example of a potential "gotcha" with the use of max
, unavoidable since max
needs to be defined to return a reference in order to avoid expensive copies (and to avoid the requirement of a copy constructor)?
可能在现实生活中,最好的编程做法是定义一个 max
版本,该版本通过值而不是通过引用返回结果,出于这个问题中讨论的原因?
Might there be real-life circumstances in which it would be good programming practice to define a version of max
that returns its result by value, rather than by reference, for the reason discussed in this question?
推荐答案
是的,它是一个悬挂的参考。
Yes, it's a dangling reference.
是的,这是一个陷阱。
按值返回的版本可能很有用,前提是您默认使用 ,并在需要时切换到按引用。如果默认情况下使用by-reference一个,仅在需要时切换到by-value,那么您仍然会感到困惑,因为认识到您需要它与意识到您应该写 const A a_ = :: max(A(),A());
。
A version that returns by value might be useful provided that you use it by default, and switch to by-reference in the cases where you need it. If you use the by-reference one by default and only switch to the by-value when you need it then you'll still fall foul of the gotcha, because realizing that you need it is the same thing as realizing you should have written const A a_= ::max(A(), A());
.
不幸的是按值一个引入了一个新的陷阱:
Unfortunately the by-value one introduces a new gotcha:
A a, b, c;
mymax(a, b) = c; // assigns to temporary, not to a or b
(实际上,看这段代码,我认为您将其称为 max_by_val
,那么您就不会写这个了。
(Actually, looking at this code I reckon if you call it max_by_val
then you won't write this).
您可以按const值返回,有些人们曾经建议操作符重载应按const值返回。但这在C ++ 11中引入了性能陷阱:
You could return by const value, and some people used to recommend that operator overloads should return by const value. But that introduces a performance gotcha in C++11:
A a, b, c;
c = constmymax(a, b); // copies from const rvalue instead of moving.
甚至在C ++ 03中,它也防止了等效的显式优化 swap( c,constmymax(a,b))
。
and even in C++03 it prevents the equivalent explicit optimization swap(c, constmymax(a,b))
.
这篇关于如果std :: max()通过引用返回(必须这样做),是否可能导致悬挂的引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!