C++ 指针上的开始/结束 (arr) - 调用 'begin(int**&)' 没有匹配函数

C++ begin/end(arr) on a pointer - no matching function for call to ‘begin(int**&)’

本文关键字:函数 begin int 调用 指针 开始 arr 结束 C++      更新时间:2023-10-16

>我想获取数组的长度。我有这个代码:

#include <iterator>
#include <iostream>
#include <string>
using namespace std;
void printArrLen(int arr[]);
int testArr [3] = {1, 4, 5};
int main() {
printArrLen(testArr);
cout << "main/testArr; Memory address: " << testArr << ", value: " << *testArr << endl;
cout << end(testArr) << endl;
}
void printArrLen(int arr[]) {
cout << "printArrLen/arr; Memory address: " << arr << ", value: " << *arr << endl;
cout << "printArrLen/testArr; Memory address: " << testArr << ", value: " << *testArr << endl;
// This works:
cout << end(testArr) << endl;
// This doesn't work - no matching function for call to 'end(int*&)':
// cout << end(arr) << endl;
// Doesn't work:
// cout << "arrLen: " << end(arr) - begin(arr) << endl;    
}

输出:

printArrLen/arr; Memory address: 0x601318, value: 1
printArrLen/testArr; Memory address: 0x601318, value: 1
0x601324
main/testArr; Memory address: 0x601318, value: 1
0x601324

在printArrLen中取消注释cout << end(arr) << endl;给出了no matching function for call to 'end(int*&)'

我知道如果arr是一个指针,begin/end(arr)行不通。 为什么他们在 printArrLen 和 main 中的 testArr 上工作,如果 testArr 似乎也是一个指针?如何在printArrLen中证明testArr不是指针,而arr是指针,而它们似乎都包含内存地址?

我知道

如果 arr 是一个指针,开始/结束(arr) 将不起作用。为什么他们在 printArrLen 和 main 中的 testArr 上工作,如果 testArr 似乎也是一个指针?

指针不是数组。

在您的代码中,

  • testArr是已用 3 个元素初始化的数组。
  • arr是数组参数。数组参数的特殊之处在于数组decays指针,因此实际传递给函数printArrLen的是一个指针(指向第一个元素arr)。

顺便说一句,初始化时不必提供数组大小。这也行(而且更好):

int testArr[] = {1, 4, 5};

我想得到一个数组的长度。

[...]

void printArrLen(int arr[]);

不是这样的。 此函数中的arr实际上是指向数组第一个元素的指针。或者更准确地说,它可能指向数组的第一个元素。这只是一个int*,可以指向任何地方。无论如何,函数内部不再大小信息。你根本无法得到它。

[]语法只是为了让您感到困惑。但是不要相信我的话 - 通过尝试这段代码来询问您的编译器:

void printArrLen(int arr[]) {}
void printArrLen(int* arr) {}

你会看到它会抱怨重新定义。

上面的arr参数相反,

int testArr [3] = {1, 4, 5};
testArr是一个数组,并在其类型中携带大小信息。

int main() {
printArrLen(testArr);

在这里你向函数传递一个指向testArr第一个元素的指针,即指向 "1" 元素的int*

// This works:
cout << end(testArr) << endl;

因为testArr是一个数组。

// This doesn't work - no matching function for call to 'end(int*&)':
// cout << end(arr) << endl;

因为arr是一个指针。


如果数组的大小仅在运行时已知,请使用std::vector,如果在编译时已知,则使用std::array。两个容器始终知道自己的大小。


如何在 printArrLen 中证明testArr不是指针 当它们似乎都包含内存地址时,arr

这个问题没有看起来那么有意义。

考虑一下:

int main()
{
int i = 0;
double d = 0.0;
}

现在,你怎么能"证明"i不是double而是d

答案是你不必"证明"它,因为显然,你已经知道了。

从技术上讲,您的问题当然还有另一个答案,那就是使用typeid......

#include <typeinfo>
#include <typeindex>
#include <iostream>
void printArrLen(int arr[]);
int testArr [3] = {1, 4, 5};
int anotherTestArr [3] = {1, 4, 5};
int yetAnotherTestArr [4] = {1, 4, 5, 6};
int main() {
printArrLen(testArr);
}
void printArrLen(int arr[]) {
std::cout << (std::type_index(typeid(arr)) == std::type_index(typeid(testArr))) << "n";
std::cout << (std::type_index(typeid(anotherTestArr)) == std::type_index(typeid(testArr))) << "n";
std::cout << (std::type_index(typeid(yetAnotherTestArr)) == std::type_index(typeid(testArr))) << "n";
}

这对您没有任何直接用途,但它具有很大的教育价值。它将打印:

0
1
0

此示例演示不同大小的数组是不同的类型,指针是所有数组类型的不同类型。

testArr

不是一个指针,它是一个包含3元素的数组。

arr是一个指针 - 没有足够的知识来使beginend工作,因为编译器不知道它指向一个数组(以及假设数组的大小)。

我的建议是:使用std::arraystd::vector,具体取决于您需要做什么。如果要使用老式数组,请更改printArrLen以采用数组引用:

template <size_t N>
void printArrLen(int (&arr)[N]) {
/* ... */
}

魔杖盒示例