sizeof and pass-by-reference
I am hoping that someone can explain the following behaviour.
Suppose I am trying to implement a function which determines the length of any array, but want to avoid using macros. For e.g
#define array_length(x) ( sizeof(x) / sizeof(x[0]) )
Given that the function must work with any parameter type, I must use templates.
My first try looked something like this.
template <typename T>
inline size_t
array_length(const T argument) {
return sizeof(argument) / sizeof(argument[0]);
}
This doesn't work because the argument is treated as a pointer. Once T is changed to T& everything works dandy.
I am wondering if anyon开发者_JAVA技巧e can say something about what is happening at the level of language implementation. For example, what extra information is passed to a function when references are used as function arguments?
Let's consider two function templates:
template <typename T> void f(T);
template <typename T> void g(T const&);
And let's say we have an array:
int a[10];
What happens when we call f(a);
? Since we don't explicitly provide an argument to the template, argument deduction kicks in and the compiler tries to figure out what T
is based on the argument. The argument is of type int[10]
. T
will never be deduced to be a reference type and you cannot pass an array by value, so the array-to-pointer implicit conversion takes place and T
is deduced to be int*
.
What happens when we call g(a);
? Again, argument deduction is used to determine what T
is. The parameter is of type reference to T
, though, so T
can be deduced directly to be int[10]
and the array-to-pointer conversion does not take place.
Note that the best solution to finding the length of an array is to explicitly require that the template get an array:
template <typename T, std::size_t N>
std::size_t array_length(T const (&)[N]) { return N; }
AFAIK there is no good way to do that outside of macros. Which is why I'd rather use std::array
(new class in C++0x, evolved from boost::array, which is available also for "old" C++) or a std::vector
.
I know you're looking for more technical info, but you can get the # of elements in an array without macros using template argument deduction:
template<typename T, size_t N>
size_t ElementCount(const T (&x)[N])
{
return N;
}
Use it like this:
int x[15];
size_t elements = ElementCount(x);
精彩评论