通过函数确定字符串数组的大小

size of string array through function

本文关键字:数组 字符串 函数      更新时间:2023-10-16

如何查找传递给函数的字符串数组的大小。大小应在函数内部计算。

#include<iostream>
using namespace std;

template <typename T,unsigned S>
unsigned arraysize(const T (&v)[S]) { return S; }
void func(string args[])
{
   unsigned m=arraysize(args);
   cout<<m;
}
int main()
{
    string str_arr[]={"hello","foo","bar"};
    func(str_arr);  
}

我不明白的是:

如果语句arraysize(str_arr)在main中使用,它不会产生问题。str_arr是一个数组,所以str_arr作为一个指针,所以当我们使用arraysize(str_arr)时,这意味着我们将地址发送给arraysize函数。(如果我说错了请指正)。

但是在函数func()中,我不明白为什么会有问题,即语句arraysize(args)发送字符串数组args的地址(或指针args的地址)..还是因为它变成了双指针而变得更复杂??解释一下好吗?

str_arr是一个字符串数组。当您执行sizeof(str_arr)时,您将获得该数组的大小。然而,尽管args看起来像一个字符串数组,但它不是。看起来像数组的实参实际上是指针类型的。也就是说,string args[]被编译器转换为string* args。当你执行sizeof(args)时,你只是获得指针的大小。

您可以将数组的大小传递给函数,也可以使用模板参数size(如arraysize所做的那样)接受对数组的引用:

template <size_t N>
void func(string (&args)[N])
{
   // ...
}

发送给函数时无法确定数组的大小。您还必须记住,只有一个指向数组的指针被发送给函数,这使得计算数组的大小在理论上是相当不合理的。

数组大小的信息在函数中永远不可见,因为当您决定使用string args[]作为参数时,您将其丢弃。从编译器的角度来看,它与string* args相同。您可以将函数更改为:

template<size_t M>
void func(string (&args)[M])
{
   cout<<M;
}

但是你好像已经知道了,对吧?

如果语句arraysize(str_arr)在main中被使用,它不会引起问题。str_arr是一个数组,所以str_arr作为一个指针,所以当我们使用arraysize(str_arr)时,这意味着我们将地址发送到arraysize函数。(如果我说错了请指正)。

我必须在这里纠正你。你提出了正确的前提,但得出了错误的结论。

关键是str_arr确实是main中的一个数组。虽然在许多(大多数)表达式上下文中数组衰减为指针,但在初始化对数组的引用时不会出现这种情况。这就是为什么array_size被声明为引用数组形参的原因——这是拥有数组类型形参的唯一方法,这意味着它带有定义的长度。

这不是func的情况。当函数形参被声明为普通数组类型时,指针衰减的数组将应用于该声明。你对func的声明等同于void func(string * args)。因此,args是一个指针,而不是数组。您可以将func调用为

string str_non_array;
func(&str_non_array);

因此,对数组的引用不能绑定到它。无论如何,args已经完全丢失了关于它所指向的数组大小的所有信息。

您可以使用与arraysize相同的引用到数组的技巧:将func声明为

template <std::size_t N>
void func(string (&args)[N]);

但是在任何地方都这样做是不切实际的(如果天真地应用于所有数组处理代码,可能会导致代码膨胀)。与其他语言中可用的具有长度的数组等效的c++是std::vector<string>(用于动态大小的数组)或std::array<string,N>(用于编译时已知的固定大小)。请注意,后者可能导致与上面提到的相同的代码膨胀,因此在大多数情况下,std::vector<string>将是需要传递给各种函数的数组的首选类型。

Dmitry是对的,我想进一步解释一下。它发生的原因是因为数组在c++中不是第一类公民,当作为参数传递时,它会衰减为指针,而你在调用函数中得到的是指向其第一个元素的指针,并且大小丢失。您可以将c++数组作为函数参数,以查看有哪些可用的替代选项。