【问题标题】:C++ Not Requiring Array Length with Recursive Sorting AlgorithmsC++ 使用递归排序算法不需要数组长度
【发布时间】:2012-10-30 05:06:56
【问题描述】:

有些人可能知道也可能不知道您可以使用以下代码获取函数的数组参数的大小:

template<typename DataType, size_t SIZE>
void SortingAlgorithm(DataType (&array)[SIZE])
{
  ...
  return;
}

其中 SIZE 可用于表示数组中元素的数量,允许程序员使用您的函数将数组作为参数传递而无需显式传递长度。例如,程序员可以这样做:

SortingAlgorithm( arrayToBeSorted ); //the length is not passed here, which is fine

对于可以相对容易地以迭代方式实现的算法,这很好。但我试图用其他递归算法来做到这一点。每个人的代码可能如下所示:

template<typename DataType, size_t SIZE>
void SortingAlgorithm(DataType (&array)[SIZE])
{
  DataType newArray[SIZE];
  memcpy(newArray,array, SIZE);  //copy to a new array
  SortingAlgorithm( newArray );
  ...
  return;
}

但这每次都会抛出一个错误,提示程序需要不同的参数类型,类型转换失败,并显示尝试多次对 newArray 数组的 SIZE 说明符进行类型转换,程序失败。但是,如果我在进行递归调用之前使用实际值来定义 newArray 的大小,它不会吐出这些错误,如下所示:

DataType newArray[10]; //arbitrary number, but the compiler accepts this.

为什么可变大小的数组会导致错误?还有没有办法实现一个递归算法,它接受一个数组作为输入,但不需要数组的长度作为参数,因为它可以在函数调用中每次确定数组的长度?

【问题讨论】:

  • SortingAlgorithm&lt;DataType, SIZE&gt;( newArray ); 工作吗?
  • 您知道这样做的不利之处在于,将为您需要排序的每个大小的数组生成一个新的排序例程实例,对吧?除非您对交易代码大小非常激进以提高速度,否则模板分类器的主体应该类似于SizeGenericSortingAlgorithm(array, SIZE),调用template&lt;typename DataType&gt; void SizeGenericSortingAlgorithm(DataType *array, size_t size)
  • 你能贴出真实的例子吗?错误是什么?
  • 这里的目标是弄清楚我是否可以通过不需要程序员跟踪他/她正在使用的数组的大小来方便地使用递归排序算法。
  • @kjh 在这种情况下为什么不使用 std::vector?

标签: c++ arrays templates types recursion


【解决方案1】:

制作一个具有一定大小的辅助函数,它可以在您的其他函数内部使用,并且没有人需要知道它。例如:

template<typename DataType>
void SortingAlgorithm_helper(DataType * ptr, size_t size)
{
    ...
    SortingAlgorithm_helper(ptr + 1, size - 1);
    ...
}

template<typename DataType, size_t SIZE>
void SortingAlgorithm(DataType (&array)[SIZE])
{
    ...
    SortingAlgorithm_helper(newArray,SIZE);
    ...      
}

通过您的 cmets,您正在考虑切换到矢量。好吧,您不必在这里做出选择。您可以使代码更通用以处理两者。我们没有将指针和大小传递给辅助函数,而是传递了两个指定范围的迭代器。然后我们修改main函数接受任何容器,只要std::beginstd::end在上面工作。

template<typename Iterator>
void SortingAlgorithm_helper(Iterator first, Iterator last)
{
    ...
    SortingAlgorithm(++first, last);
    ...
}

template<typename Container>
void SortingAlgorithm(Container & c)
{
    ...
    SortingAlgorithm_helper(std::begin(c), std::end(c));
    ...
}

这应该处理内置数组std::vectorstd::arraystd::deque。如果您将迭代器上执行的操作限制为双向(++ 和 --),那么它也应该处理 std::list

【讨论】:

    【解决方案2】:

    不要这样做。相反,请使用以下选项之一:

    • 使用std::vector(它有一个size() 方法)而不是数组。
    • 将数组的大小作为附加参数传递给您的函数。

    对于递归算法,不要只是将元素复制到一个新数组中,这很耗时。

    相反,传入两个指针,指向要处理的数组部分的开头和结尾(看看 STL 算法是如何工作的,std::sort 不使用容器,而是使用两个迭代器) .

    但是请注意,这实际上取决于您使用的算法的细节,有些算法实际上可能需要显式复制,但您应该尽可能避免。

    【讨论】:

      【解决方案3】:

      模板在编译时生成代码,指定一个像 10 这样的值允许它生成代码,因为它知道使用什么值。指定在编译时无法确定的东西(比如在运行时只有一个值的变量)意味着它不知道在生成代码时使用什么值。

      【讨论】:

        【解决方案4】:

        编译器需要在编译时计算大小,而不是运行时。我的编译器接受您编写的代码,但显然您无法确定大小。你可以像这样明确地告诉它大小:

        SortingAlgorithm&lt;DataType, SIZE&gt;( newArray );.

        这行代码的两个版本都适用于我的编译器。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-01-02
          • 2013-11-18
          • 1970-01-01
          • 1970-01-01
          • 2019-01-09
          • 2012-11-06
          • 2019-10-29
          • 2017-06-06
          相关资源
          最近更新 更多