sizeof和pass-by-reference

时间:2011-08-11 20:01:42

标签: c++ templates sizeof

我希望有人可以解释以下行为。

假设我正在尝试实现一个确定任何数组长度的函数,但希望避免使用宏。例如

#define array_length(x) ( sizeof(x) / sizeof(x[0]) )

鉴于该函数必须适用于任何参数类型,我必须使用模板。

我的第一次尝试看起来像这样。

template <typename T>
inline size_t
array_length(const T argument) {
    return sizeof(argument) / sizeof(argument[0]);
}

这不起作用,因为参数被视为指针。一旦T改为T&amp;一切都很有效。

我想知道是否有人可以就语言实施水平发生的事情说些什么。例如,当引用用作函数参数时,将哪些额外信息传递给函数?

3 个答案:

答案 0 :(得分:5)

让我们考虑两个功能模板:

template <typename T> void f(T);
template <typename T> void g(T const&);

让我们说我们有一个数组:

int a[10];

当我们致电f(a);时会发生什么?由于我们没有明确地为模板提供参数,因此参数推断会启动,编译器会尝试根据参数找出T。参数类型为int[10]。永远不会推断T是引用类型,并且您不能按值传递数组,因此会发生数组到指针的隐式转换,并推导Tint*

当我们致电g(a);时会发生什么?同样,参数推导用于确定T是什么。该参数的类型为 T 的引用,因此T可以直接推导为int[10],并且数组到指针的转换不会的地方。

请注意,找到数组长度的最佳解决方案是明确要求模板获取数组:

template <typename T, std::size_t N>
std::size_t array_length(T const (&)[N]) { return N; }

答案 1 :(得分:2)

AFAIK没有好办法在宏之外做到这一点。这就是为什么我宁愿使用std::array(C ++ 0x中的新类,从boost::array演化而来,也可用于“旧”C ++)或std::vector

答案 2 :(得分:1)

我知道你正在寻找更多的技术信息,但你可以使用模板参数推导得到数组中没有宏的元素数量:

template<typename T, size_t N>
size_t ElementCount(const T (&x)[N])
{
    return N;
}

像这样使用:

int x[15];
size_t elements = ElementCount(x);