C++ Primer中陈述
在C ++中,指针和数组紧密交织在一起。尤其如此 我们将看到,当我们使用数组时,编译器通常会转换 数组到指针。
我想使用迭代器来打印数组。下面的程序工作正常,但是当我尝试打印arr2
或arr3
时,如果我没有弄错,类型为int *
,我会收到错误(判断为&运算符意味着参考下面)。
error: no matching function for call to ‘begin(int*&)’
int main(int argc, char** argv) {
int arr[] = {0,1,2,3,4,5,6,7,8,9};
auto arr2 = arr;
auto arr3(arr); // I think arr2 and arr3 are of same type
for(auto it = std::begin(arr) ; it != std::end(arr) ; ++it)
std::cout << *it << " ";
std::cout << std::endl;
return 0;
}
考虑到该语句,如果编译器将数组转换为指针,则该程序如何使用arr
和std::begin()
打印std::end()
的内容,并且不适用于arr2
或arr3
如果所有这些都是整数的指针?
修改
如果我无法说清楚,我很抱歉。我希望我能通过这次编辑澄清问题。
现在我知道begin()
和end()
不能使用指针(感谢答案),我想知道引用的文本是不是真的,因为它指定有一个数组 - &gt;指针转换。如果文本说的是真的那么arr
的类型应该是指针。此时引用的文字是否有问题?
另外,有没有什么方法可以使用begin()
和end()
指定大小(而不是STL容器),可能使用以下构造函数?
template< class T, size_t N >
T* begin( T (&array)[N] );
答案 0 :(得分:7)
数组很容易转换为指针,但并非总是如此。例如,如果您获取数组的地址或获取引用,则原始数组类型不会丢失:
int a[10];
int (&ar)[10] = a; // fine
int (*ap)[10] = &a; // also fine
但是,当您以一种大多数其他类型将被复制的方式使用数组时,数组将转换为指针,而是复制指针。
在您的示例中,如果您将其作为参考,则可以使用arr2:
auto &arr2 = arr;
现在arr2
的类型为int (&)[10]
,而不是int *
。
答案 1 :(得分:2)
因为std::begin
是为数组定义的,而不是为指针定义的。数组类型与指针类型不同。
这里的问题是显然auto arr2 = arr
会将类型从数组类型降级为指针类型。
请注意,问题实际上是std::end
而不是std::begin
。毕竟,std::end
如何能够将指针指向最后的+ 1元素,当它所有的元素都是指向第一个元素的指针时?它不能,因此无法为指针类型定义std::end
,因此std::begin
对指针类型没有任何意义。
准确地说,arr
的类型为int[10]
,而arr2
和arr3
的类型为int*
。前者可以降级为后者,但反之亦然。
答案 2 :(得分:2)
此处,auto
会将arr
(数组类型)衰减为指针。 std::begin
和std::end
只能用于容器或数组,但不能用于指针。
来自C ++ 11标准
§7.1.6.4自动说明符 [dcl.spec.auto]
1 auto类型说明符表示声明的变量类型应从其初始化程序中推导 或者函数声明符应包含尾随返回类型。
您的代码无法在此处运行,因为auto
无法推断出数组类型。就像:
char a[5];
auto b[5] = a; // error, a evaluates to a pointer, which does
// not match the array type
要使其正常工作,只需使用std::vector
之类的C ++容器:
vector<int> arr = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
答案 3 :(得分:1)
std::begin
和std::end
使用C样式数组的参数。
std::end
的可能实现是:
template<class T, std::size_t sizeOfArray>
constexpr T *end(T (&array)[sizeOfArray])
{
return &array[sizeOfArray];
}
这种方式arr
在调用std::end(arr)
时不会在指针中转换(并且有关数组大小的信息不会丢失......该函数只接受精确的数组sizeOfArray
个元素作为参数)。
template<class T>
T *end(T array[])
{
// ?
}
由于T array[]
在用作函数参数时表现得像平面指针(T *array
)而不是真正的数组,所以
无法工作。
auto
将数组arr
衰减为指针,技巧不再有效。