【问题标题】:Obtaining a pointer to the end of an array获取指向数组末尾的指针
【发布时间】:2011-06-13 03:28:26
【问题描述】:

我使用以下模板来获取指向数组最后一个元素之后的指针:

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

【问题讨论】:

  • 由于您必须将数组的大小传递给函数,您真正从中得到了什么,而使用array 模板却无法获得?
  • @Zac:我没有,这个函数只有一个参数。模板参数n是自动推导出来的,你只要说end_of(array)如示例代码所示。
  • 在这种情况下,您将遇到的问题是处理动态数组,因为 n 将只是单个 T 的大小。
  • @Zac:不。你不能将指向数组第一个元素的指针传递给模板,因为指针不是数组。
  • 这正是我所说的问题:您不能将它与动态分配的数组一起使用。

标签: c++ arrays templates pointers pass-by-reference


【解决方案1】:

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

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 始终以字符数返回大小。

【讨论】:

  • 啊,我很确定这就是我想到的问题。谢谢!
  • +1 用于解决问题。从技术上讲,并不是在编译时不对其进行评估,而是即使在编译时进行评估,该值也不是编译时常量。
【解决方案2】:

我看到的唯一问题是,如果您在编译时不知道长度,您的模板将不知道在其中放入什么。所以你必须说test+x 或其他任何东西,现在你有两种不同的方式来做同样的事情。

就我个人而言,我宁愿只使用vector&lt;int&gt;,因此已经为我定义了end()。如果您需要该数组,可以使用 &amp;v[0]

【讨论】:

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

你也需要一个 const 版本。但是,据我所知,这种方法没有实际问题——我认为它很常用。

【讨论】:

  • 不,上面的代码也适用于const 数组。如果你传递了一个const Foo[n] 数组,那么T 被推断为const Foo 而不仅仅是Foo
  • @Fred 是对的。它只对end_of(A().a); 失败,其中Astruct A { int a[1]; }; 定义(因为右值和非常量引用),但我认为这在这种情况下还不错,而是一件好事。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-07
  • 2016-07-30
相关资源
最近更新 更多