本地数组长度与从函数调用时不同

时间:2015-02-04 09:18:34

标签: c++ arrays c++11 decltype

在以下代码中,std::extent<decltype(columns)>::value计算给定数组的长度。但是,当数组是函数参数时,编译器的行为方式不同。有人可以帮我解决这个问题吗?

输出:

  

本地数组长度:5

     

函数数组长度:0

代码:

#include <iostream>
#include <string>

void showcolumns_num(std::string columns[])
{
    int columns_num=std::extent<decltype(columns)>::value;
    std::cout<<"function array length: "<<columns_num<<std::endl;
}


int main()
{
    std::string column_list[]={"col1","col2","col3","col4","col5"};

    // local calculation of column number
    int columns_num=std::extent<decltype(column_list)>::value;
    std::cout<<"local array length: "<<columns_num<<std::endl;

    // function calculation of column number
    showcolumns_num(column_list);

    return 0;
}

3 个答案:

答案 0 :(得分:4)

你必须通过引用传递数组,以避免衰减到指针,这会失去大小信息:

template <std::size_t N>
void showcolumns_num(std::string (&columns)[N])

Live example

答案 1 :(得分:2)

简短的回答是:不要使用数组。而不是string columns[N];,请使用vector<string> columns;vector<string> columns(N,"");。在这个答案中,我将更多地谈论数组,它们是有趣的&#34;。但数组很有趣&#34;在癌症有趣的方式,有人必须了解癌症,但我们想摆脱它,大多数人不想成为专家。

C数组真的很奇怪。它们不能通过值传递,但它们可以通过引用传递,而C ++使它变得非常容易。如果你确定 - 作为一项智力练习 - 传递数组,那么你可以使用它:

 template<size_t N>
 void showcolumns_num(std::string (&columns)[N])

非数组类型(如intstruct Personlist<vector<string>>)可以通过引用传递值。但数组不能通过值传递。

如果您尝试按值传递数组,编译器将执行一个技巧,而不是将指针传递给数组的第一个元素。这称为指针衰减

这意味着,在没有警告的情况下,编译器将重写您的函数声明

void showcolumns_num(std::string columns[]) { // this is what you write
// changed to
void showcolumns_num(std::string* columns) { // ... but this is what you get

,对showcolumns_num的每次调用都将改为:

showcolumns_num(column_list); // this is what you write
// changed to
showcolumns_num(&(column_list[0])); // ... but this is what you get

这背后的原因是历史性的,并且与早期的B语言有关。

变量被声明为局部变量,或全局变量或函数参数。对于局部变量和全局变量,编译器通常会尊重您的意愿,但不会考虑函数参数:

void foo(int x[5]) { // silently converted to  int *x
    int y[10];       // y really will be an array
}

答案 2 :(得分:2)

因为声明:

void showcolumns_num(std::string columns[])

与:

相同
void showcolumns_num(std::string * columns)

但声明:

std::string column_list[]={"col1","col2","col3","col4","col5"};

与:

相同
std::string column_list[5]={"col1","col2","col3","col4","col5"};

所以编译器不知道函数内部的数组大小。 只需使用std::vector< std::string >