开发者

sizeof and pass-by-reference

开发者 https://www.devze.com 2023-03-27 18:08 出处:网络
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

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);
0

精彩评论

暂无评论...
验证码 换一张
取 消