将数组作为 C++ 中方法的 const 参数传递

Posted

技术标签:

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

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

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

void myMethod(int * const inTab)

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

【问题讨论】:

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

【讨论】:

以上是关于将数组作为 C++ 中方法的 const 参数传递的主要内容,如果未能解决你的问题,请参考以下文章

C++ Boost - 序列化错误 - 将“const B”作为“this”参数传递会丢弃限定符

在 C++ 中将不同大小的常量数组作为函数参数传递

C++中数组作为形参进行传递(转)

将内联双精度数组作为方法参数传递

将函数作为参数传递。 C++

C++ 数组与字符串⁽²³⁾|函数与数组