重载的模板参数 - 为什么这个例子有问题?

时间:2010-11-01 22:46:07

标签: c++ templates

我开始阅读C ++模板 - Josuttis和Vandevoorde的完整指南。 我的小脑子被困住了。

作者声明“您应该将更改限制为参数数量或明确指定模板参数”,使用此作为导致问题的示例:

template <typename T>
inline T const& max (T const& a, T const& b)
{
    return a < b ? b : a;
}

// maximum of two C-strings
inline char const* const& max( char const* a, char const* b)
{
    return std::strcmp(a, b) < 0 ? b : a;
}

template <typename T>
inline T const& max (T const& a, T const& b, T const& c)
{
    return max( max(a,b), c);
}

他们说使用max的3参数版本是一个错误 -

const char * s1 = "fred";
const char * s2 = "anica";
const char * s3 = "lucas";
::max(s1, s2, s3); // ERROR

“因为对于C字符串,max(a,b)创建一个新的临时本地值,该值可由函数通过引用返回。”但我编译并运行得很好。

有人可以解释一下作者在这个例子中说的是什么吗?

4 个答案:

答案 0 :(得分:3)

问题是“最多两个C字符串”的重载按值取两个参数,但随后返回对其中一个参数的引用。返回对局部变量的引用是一个坏主意(一旦局部变量在函数返回时被销毁,就不能使用引用,所以它没用)。

你可以通过const引用取const char*两个来修复它:

char const* const& max( char const* const& a, char const* const& b)

原始版本可能会编译,但是如果您使用从max调用返回的值(您执行此操作,因为您在调用max(a,b)时使用max(max(a,b),c)的结果),行为未定义(因为您正在使用已被销毁的对象)。

答案 1 :(得分:1)

你没有参考a和b。通过引用返回其中一个意味着您将返回对参数的引用,该参数是堆栈上的局部变量。

答案 2 :(得分:0)

我不确定他们想说什么,因为我看不出它会如何创建临时局部变量,但是使用带有C字符串的模板可能会以其他不寻常的方式失败,即不同长度的数组之间的差异,char数组和char *等之间的差异

http://codeidol.com/cpp/cpp-templates/Tricky-Basics/Using-String-Literals-as-Arguments-for-Function-Templates/可以作为这些问题的良好参考。

答案 3 :(得分:0)

该书的第二个max函数比较了两个C字符串,实际上定义为

inline char const* max( char const* a, char const* b)
{
    return std::strcmp(a, b) < 0 ? b : a;
}

因此max(a,b)内的电话max(max(a,b),c)不是罪魁祸首。这是因为max(max(a,b),c)已重载解析为max( char const* a, char const* b),其中a获取max(a,b)的返回值。但是此函数返回,3-arg max返回引用;因此错误。