C ++不需要使用递归排序算法的数组长度

时间:2012-11-09 20:31:24

标签: c++ arrays templates types recursion

有些人可能知道或者可能不知道你可以使用这段代码获得函数数组参数的大小:

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.

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

4 个答案:

答案 0 :(得分:7)

创建一个大小的辅助函数,它可以由你的其他函数在内部使用,没有人必须知道它。例如:

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

根据您的意见,您正在考虑切换到矢量。好吧,你不必在这里做出选择。您可以使代码更通用以处理这两者。我们传入两个指定范围的迭代器,而不是将指针和大小传递给辅助函数。然后我们修改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

答案 1 :(得分:4)

不要这样做。而是使用以下选项之一:

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

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

相反,将两个指针传递给要处理的数组部分的开头和结尾(查看STL算法的工作原理,std::sort不带容器,而是需要两个迭代器)。

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

答案 2 :(得分:1)

模板在编译时生成代码,指定类似10的值允许它生成代码,因为它知道要使用的值。指定在编译时无法确定的内容(如在运行时只有值的变量)意味着它不知道在生成代码时要使用的值。

答案 3 :(得分:0)

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

SortingAlgorithm<DataType, SIZE>( newArray );

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