为何int(*p)[3]无法使用std::begin/std::end,而int(&p)[3]可以?
为什么
int (&a)[3]和int (*a)[3]在使用begin()/end()时表现不同? 先看你给出的两个代码片段:
能正常运行的版本:
void foo(int (&a)[3]) { auto ibegin = begin(a); auto ebegin = end(a); }
无法运行的版本:
void foo(int (*a)[3]) { auto ibegin = begin(a); auto ebegin = end(a); }
你之前觉得这俩类型含义相同?其实完全不是一回事!我给你掰扯清楚:
int (&a)[3]是对长度为3的int数组的引用。当你把数组传递给这个函数时,a直接绑定到原数组上,它的类型就是int[3](数组类型)。标准库的begin()和end()函数专门有针对数组的重载,能直接识别数组的长度,返回指向数组首元素和尾后位置的指针,所以这段代码能正常编译运行。int (*a)[3]是指向长度为3的int数组的指针。这里的a本质是个指针变量,存储的是数组的地址。虽然指针的类型里包含了数组长度的信息,但标准库的begin()和end()并没有针对“指向数组的指针”的重载——对于函数来说,它只看到一个指针,不知道这个指针背后是个多大的数组,自然没法直接调用begin(a)。如果要让这段代码正常工作,你得手动解引用这个指针,拿到它指向的数组:void foo(int (*a)[3]) { auto ibegin = begin(*a); auto ebegin = end(*a); }这样
*a就代表指针指向的那个int[3]数组,begin()和end()就能正常处理了。
简单来说,引用是原数组的“别名”,而指针是指向数组的“地址变量”,两者的语义完全不同,这就是为什么一个能直接用begin()/end(),另一个不行。
内容的提问来源于stack exchange,提问作者Rick
相关产品推荐
相关产品推荐

