【问题标题】:Sized array in function signature [duplicate]函数签名中的大小数组[重复]
【发布时间】:2021-09-19 08:58:43
【问题描述】:

在函数签名中定义大小数组(相对于更常用的无大小数组或指针语法)是否有任何影响?我的编译器完全忽略了它,如下面的示例代码所示(虽然它在传递较小的数组时会打印一些垃圾值)。

#include <iostream>
using namespace std;

void printArray(int intArray[5]) {
  for (int i = 0; i < 5; i++) {
    cout << intArray[i] << " ";
  }
  cout << endl;
}

int main()
{
  int array1[1] = {1}; // Smaller array size than in the function signature
  cout << "\nInvocation 1\n";
  printArray(array1);

  int array2[4] = {1, 2, 3, 4}; // Smaller array size than in the function signature
  cout << "\nInvocation 2\n";
  printArray(array2);

  int array3[8] = {1, 2, 3, 4, 5, 6, 7, 8}; // Larger array size than in the function signature
  cout << "\nInvocation 3\n";
  printArray(array3);

  return 0;
}

【问题讨论】:

  • 是的,它更像是一个演员表。在 C++ 中,与 C 不同,您可以通过引用传递数组,它将保留大小。
  • 如果您使用 std::array,C++ 语法(和语义)会变得更加清晰,例如printArray 变为 printArray(const std::array& intArray)。这意味着您可以同时使用 const 和 reference 来显示您的意图(仅从数组中读取,不要复制)。作为奖励,您可以执行 template<:size_t n> void printArray(const std::array&) 来覆盖更多大小的数组。
  • void printArray(int[5])void printArray(int*)完全相同。如果你定义两者,你会得到:error: redefinition of 'void printArray(int*)'.

标签: c++


【解决方案1】:

在函数签名中定义大小数组(相对于更常用的无大小数组或指针语法)是否有任何影响?

不,不是你这样做的方式。

另一方面,这会使 intArray 成为对作为参数传递的数组的引用:

void printArray(int (&intArray)[5]) {
  for (int i = 0; i < 5; i++) {
    cout << intArray[i] << " ";
  }
  cout << endl;
}

更通用的形式是使其成为函数模板。然后将为您调用它的每个数组大小实例化一次:

template<std::size_t N>
void printArray(int (&intArray)[N]) {
  for (int i = 0; i < N; i++) {
    cout << intArray[i] << " ";
  }
  cout << endl;
}

【讨论】:

    【解决方案2】:

    在函数签名中定义大小数组(相对于更常用的无大小数组或指针语法)是否有任何影响?

    不,它没有,传递的数组参数将始终衰减为指向其第一个元素的指针,从编译器的角度来看,放置大小确实毫无意义,它会忽略它,有void printArray(int intArray[5]){...}void printArray(int intArray[]){...} 或 @ 987654323@基本一样。

    我的编译器完全忽略了它,如下面的示例代码所示(虽然它在传递较小的数组时会打印一些垃圾值)。

    这是有道理的,因为在循环中您正在访问数组边界之外的元素,因此行为是未定义的。

    【讨论】:

    • 我认为多维数组也是如此,即第一个维度,如果在函数签名中明确指定,也将被忽略,而其他维度则不会。
    • @Sandeep,是的,没错。
    【解决方案3】:

    这就是我使用 std::array 的方式

    #include <array>
    #include <iostream>
    
    template<typename type_t, std::size_t N>
    void printArray(const std::array<type_t,N>& values)
    {
        for (const auto& value : values)
        {
            std::cout << value << " ";
        }
        std::cout << std::endl;
    }
    
    void printArray_s(const std::array<int, 5>& values)
    {
        for (const auto& value : values)
        {
            std::cout << value << " ";
        }
        std::cout << std::endl;
    }
    
    // helper function to avoid having to type value of N in std::array (syntactic sugar)
    // used for array3
    template<typename array_type, typename... args_t>
    constexpr auto make_array(const args_t&&... values)
    {
        return std::array<array_type, sizeof...(args_t)>{ static_cast<array_type>(values)... };
    }
    
    
    int main()
    {
        // Smaller array size than in the function signature
        std::array<int,1> array1{ 1 }; 
        std::cout << "\nInvocation 1\n";
        //printArray_s(array1); // <== will correctly give compiler error
    
        // Smaller array size than in the function signature
        std::array<int, 4> array2{ 1, 2, 3, 4 };
        std::cout << "\nInvocation 2\n";
        printArray(array2);
    
        // Larger array size than in the function signature
        auto array3 = make_array<int>(1, 2, 3, 4, 5, 6, 7, 8 ); 
        std::cout << "\nInvocation 3\n";
        printArray(array3);
    
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-27
      • 2015-04-24
      • 1970-01-01
      • 2018-05-12
      • 1970-01-01
      • 2014-11-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多