我开始阅读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)
创建一个新的临时本地值,该值可由函数通过引用返回。”但我编译并运行得很好。
有人可以解释一下作者在这个例子中说的是什么吗?
答案 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
返回引用;因此错误。