获取数组末尾的指针

14
我使用以下模板来获取指向数组最后一个元素之后的指针:
template <typename T, size_t n>
T* end_of(T (&array)[n])
{
    return array + n;
}

我似乎记得这种方法存在一些问题,但我不记得是什么了。我认为它与类型参数或函数参数的选择有关,但我不确定。因此,只是作为一个健全性检查,你是否看到上面的代码存在任何问题?小型使用测试:

int test[] = {11, 19, 5, 17, 7, 3, 13, 2};
std::sort(test, end_of(test));

在这种情况下,你会遇到一个问题,那就是处理动态数组,因为 n 只会是单个 T 的大小。 - Zac Howland
@Zac:不行。你不能将指向数组第一个元素的指针传递给模板,因为指针不是数组。 - fredoverflow
我在运行时和编译时没有区分(实际上这两个都是问题,但这不是重点)。这是您使用此模板可能遇到的唯一问题。虽然如此,我仍然建议您最好使用std::array模板类,从而避免完全创建end_of函数的需要。 - Zac Howland
@Zac Howland:有一种奇怪的动态分配数组的方式(不是指针类型,而是数组类型),它滥用了 new []typedef int array[10]; array* a = new array[1]; 这基本上等同于 new int array[1][10];。尽管这表示一个在运行时动态分配的数组,但数组的大小仍必须是编译时常量,因为除了第一个维度之外 new [] 中的所有都必须是编译时常量。那个动态分配的数组可以传递给上面的模板作为 end_of(*a) 的参数。请再次注意,我们处理的是指向数组的指针。 - David Rodríguez - dribeas
对于那些使用C++11的人,他们可以直接使用库函数std::end - legends2k
显示剩余4条评论
3个回答

9

您的提案并不一定在编译时进行评估,这取决于优化。以下内容是在编译时计算的:

template <typename T, size_t N> char (&array(T(&)[N]))[N];

int main()
{
  int myArray[10];

  std::cout << sizeof array(myArray) << std::endl;

  return 0;
}

它的工作原理是创建一个char类型的数组,该数组元素数量与给定数组相同。sizeof总是返回char数的大小。


啊,我相当确定那就是我心中所想的问题。谢谢! - fredoverflow
1
+1 是为了提出这个问题。从技术上讲,它并不是在编译时未被评估,而是即使在编译时进行了评估,该值也不是编译时常量。 - David Rodríguez - dribeas

2
我看到的唯一问题是,如果你在编译时不知道长度,那么你的模板就不知道要放什么了。因此,你必须说test+x或者其他东西,现在你有两种不同的方法来做同样的事情。
个人而言,我宁愿使用vector<int>,这样就已经为我定义了end()。如果你需要数组,它可以作为&v[0]使用。

1
通常,编译器知道数组的大小(唯一的例外是当您将其声明为extern而没有提供大小,然后在不同的翻译单元中定义数组)。这就是模板的全部意义。您不能将指向数组第一个元素的指针传递给模板,因为指针不是数组。 - fredoverflow
1
@chao:你也可以使用std::array,并且已经定义了end()函数(用于静态大小的数组)。 - Zac Howland
那么,对于数组你使用 end_of(a),对于指针你使用 a+8?当然,对于STL容器你使用 a.end()... - cHao
@CHao - 你能否添加一个例子,说明编译器无法知道数组变量的长度。我现在想不出来一个例子。 - T33C
@T33C:就像我之前说的那样,如果你在翻译单元A中将数组声明为extern int a[];,并在翻译单元B中将其定义为int a[100];,那么编译器就不知道翻译单元A中数组的大小。 - fredoverflow

1
你也需要一个const版本。然而,据我所知,这种方法实际上没有任何问题 - 我常常看到它被广泛使用。

2
不,上述代码也适用于“const”数组。如果传递一个“const Foo[n]”数组,则“T”被推断为“const Foo”,而不仅仅是“Foo”。 - fredoverflow
2
@Fred 是对的。它仅在 end_of(A().a); 处失败,其中 Astruct A { int a[1]; }; 定义(因为 rvalueness 和非 const 引用),但我认为在这种情况下这并不是坏事,而是一件好事。 - Johannes Schaub - litb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接