I've started reading C++ Templates - the complete guide by Josuttis and Vandevoorde. And my tiny mind is stuck.
The authors state that "You should limit your changes to the number of parameters or to specifying template parameters explicitly", using this as an example that causes problems:
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);
}
They say that using the 3 argument version of max is an error -
const char * s1 = "fred";
const char * s2 = "anica";
const char * s3 = "lucas";
::max(s1, s2, s3); // ERROR
"because for C-strings, max(a,b)
creates a new, temporary l开发者_高级运维ocal value that may be returned by the function by reference.". But I compiled and ran it just fine.
Can anyone explain what the author is saying in this example?
The problem is that the overload for "maximum of two C-strings" takes its two arguments by value, but then returns a reference to one of them. Returning a reference to a local variable is A Bad Idea (once the local variable is destroyed when the function returns, the reference cannot be used, so it's useless).
You can fix it by taking both of the const char*
s by const reference:
char const* const& max( char const* const& a, char const* const& b)
The original version probably does compile, but if you use the value returned from the call to max
(which you do, since you use the result of max(a,b)
when you call max(max(a,b),c)
), the behavior is undefined (because you're using an object that has been destroyed).
You didn't take a and b by reference. Returning one of them by reference means that you're returning a reference to a parameter, which is a local variable on a stack.
I'm not sure what they are trying to say because I can't see how it would create a temporary local variable, but using templates with C-strings can fail in other unusual ways, i.e. differences between arrays of different lengths, differences between a char array and a char*, etc.
http://codeidol.com/cpp/cpp-templates/Tricky-Basics/Using-String-Literals-as-Arguments-for-Function-Templates/ acts as a good reference for these issues.
The book's second max
function that compares two C-strings is actually defined as
inline char const* max( char const* a, char const* b)
{
return std::strcmp(a, b) < 0 ? b : a;
}
So the call max(a,b)
inside max(max(a,b),c)
is not the culprit. It is because max(max(a,b),c)
is overload-resolved to max( char const* a, char const* b)
where a
takes the return value of max(a,b)
. But this function returns by value and the 3-arg max
returns by reference; therefore the error.
精彩评论