考虑范式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);
}
...或者,以更简单的形式:
template<typename T> inline
T const & max(T const & lhs, T const & rhs)
{
return lhs < rhs ? rhs : lhs;
}
我理解为什么max
模板必须通过引用返回(以避免昂贵的副本并避免需要复制构造函数)。
但是,这不会导致悬空引用的可能性,如以下代码所示?
int main()
{
const int & max_ = ::max(3, 4);
int m = max_; // Is max_ a dangling reference?
}
在这种情况下,代码构建并运行良好(VS 2010)并且值m
设置为 4。但是,我觉得这max_
是一个悬空引用,因为硬编码的右值直接传递给,3
并且为这些分配的存储硬编码的右值常量可以在到达以下代码行时正确地被释放。4
max
我可以为成熟的对象设想类似的边缘情况,例如
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
需要定义为返回引用以避免昂贵的副本(并避免需要复制构造函数)?
出于这个问题中讨论的原因,在现实生活中是否可能存在良好的编程习惯来定义一个max
按值而不是按引用返回其结果的版本?