【问题标题】:passing an array as a const argument of a method in C++将数组作为 C++ 中方法的 const 参数传递
【发布时间】:2012-07-17 14:54:55
【问题描述】:

我希望能够将 const 数组参数传递给 C++ 中的方法。

我知道,当您将数组传递给方法时,它与将指针传递给数组的第一项相同,因此使用指针是一种简单的方法。

void myMethod(int * const inTab)

但有时有一个数组会更好,例如,您可以写出数组的大小。

【问题讨论】:

  • 您想传递对数组的引用。有关它的讨论,请参阅 this question 及其答案。
  • 为什么不使用 std::vector? parashift.com/c++-faq/arrays-are-evil.html
  • @avasopht:因为数组并不总是邪恶的,动态分配有时也是邪恶的。
  • 是的,非常正确。当然,重要的是要确保 Kevin 和其他查看此问题的人了解 c++-faq 以及与使用数组相关的一些危险。如果他们在使用 std::vector 时遇到问题,至少它不太可能是缓冲区溢出;)而且他们还可以开始考虑位于中间的优雅解决方案,既不分配也不直接访问数组。

标签: c++ arrays methods arguments constants


【解决方案1】:

您可以使用获取数组大小的模板:http://ideone.com/0Qhra

template <size_t N>
void myMethod ( const int (& intArray) [N] )
{
    std::cout << "Array of " << N << " ints\n";
    return;
}

编辑: 避免代码膨胀的一种可能方法是使用一个函数,该函数接受一个指针和一个大小来完成实际工作:

void myMethodImpl ( const int * intArray, size_t n );

还有一个调用它的简单模板,很容易内联。

template <size_t N>
void myMethod ( const int (& intArray) [N] )
    { myMethodImpl ( intArray, N ); }

当然,您必须找到一种方法来测试它是否始终被内联,但您确实获得了安全性和易用性。即使在并非如此的情况下,您也可以以相对较小的成本获得好处。

【讨论】:

  • 虽然是功能性的,但这并不是特别优雅,因为如果我以不同的大小调用 myMethod 100 次不同的时间,我会得到 100 个不同的函数。即时代码膨胀。根据函数的实际作用,优化器可能可以使用单个函数,但在大多数有用的情况下,我认为这不是真的......
  • @BoBTFish:谢谢。你知道是否有避免访问数组边界之外的元素的解决方案:int x = intArray[N];
  • @twalberg:这是一个很好的观点。你有什么建议?也许像我在第一篇文章中写的那样,是一种更通用但不太健壮的方法?
  • @KevinMOLCARD 这总是一个权衡...如果我知道我只有少数需要实例化的N,我可能会采用@BoBTFish 最初在答案中建议的路线。如果可能还有更多,我会在他的编辑中采用替代方案(将大小作为额外参数传递),或者将数组及其大小包装在一个小结构中,然后将引用/指针传递给该结构,以避免有太多参数。像往常一样,没有万能的解决方案。
  • 我喜欢这种技术,并将它推荐给我所有的初级开发人员。能够捕获静态 C 数组(地址和大小)而不仅仅是衰减的指针,并且担心大小不同步,这真是太好了。
【解决方案2】:

每 3.9.3:2

应用于数组类型的任何 cv 限定符都会影响数组元素类型,而不是数组类型 (8.3.4)。

和 8.3.4:1

任何 将“cv-qualifier-seq array of N T”的类型调整为“array of N cv-qualifier-seq T”,类似地 “T 的未知边界数组”。

另外,根据 8.3.5:5

之后 确定每个参数的类型,任何类型为“T 数组”或“函数返回 T”的参数是 分别调整为“指向 T 的指针”或“指向返回 T 的函数的指针”。

这意味着在一个接受数组参数的函数中,参数类型实际上是一个指针,并且由于 3.9.3:2,该指针是非 cv 限定的:

void foo(const int parameter[10]) {
    parameter = nullptr;   // this compiles!
}

这不会影响函数本身的类型,因为 8.3.5:5 中有另一个子句

生成列表后 在参数类型中,任何修改参数类型的顶级 cv 限定符在形成 函数类型。

因此,如果您希望能够传递带有 cv 限定符的数组,它必须通过引用:

void foo(const int (&parameter)[10]);

【讨论】:

    【解决方案3】:

    不确定是不是你问的,但也许是你要找的

    void func (const int array[10])
    {
        //array[0] = 12345; // this wouldn't compile, so 'const' works
    }
    
    int main ()
    {
        int array[10];
        func(array);
    }
    

    【讨论】:

    • array = 0 会编译,这是 OP 不想要的。
    • @a3f,他为什么不想要它? array=0func 不会影响它在外面
    【解决方案4】:

    如果需要数组的大小:

    template < std::size_t Size >
    void myMethod( const int ( &inTab )[ Size ] );
    

    【讨论】:

      【解决方案5】:

      试试std::vector

      void myMethod(const std::vector<int> &inTab);
      

      【讨论】:

        猜你喜欢
        • 2018-09-09
        • 2019-01-07
        • 2015-02-12
        • 2014-06-26
        • 1970-01-01
        • 1970-01-01
        • 2020-03-16
        • 1970-01-01
        • 2012-07-22
        相关资源
        最近更新 更多