在多维数组中使用 range-for 循环时"auto"的类型推断



int ia[3][4]{}之后,我运行:

for(auto row : ia) // row should be type int*
for(int *j = std::begin(*row); j!= end(*row); ++j) // error!!
std::cout << *j << std::endl;

根据C++引物第5:

因为行不是引用,所以当编译器
初始化行时,它会将每个数组元素(像任何其他
数组类型的对象一样(
转换为指向该数组的第一个元素的指针

如果row是指向ia的第一个元素的指针,那么为什么会发生错误呢?

非常感谢!

更新:

ch339.cpp: In function ‘int main()’:
ch339.cpp:10:31: error: no matching function for call to ‘begin(int*&)’
for (int *j = begin(row); j!= end(row); ++j )
^
ch339.cpp:10:31: note: candidates are:
In file included from /usr/include/c++/4.9/bits/basic_string.h:42:0,
from /usr/include/c++/4.9/string:52,
from /usr/include/c++/4.9/bits/locale_classes.h:40,
from /usr/include/c++/4.9/bits/ios_base.h:41,
from /usr/include/c++/4.9/ios:42,
from /usr/include/c++/4.9/ostream:38,
from /usr/include/c++/4.9/iostream:39,
from ch339.cpp:1:
/usr/include/c++/4.9/initializer_list:89:5: note: template<class _Tp> constexpr const _Tp* std::begin(std::initializer_list<_Tp>)
begin(initializer_list<_Tp> __ils) noexcept
^
/usr/include/c++/4.9/initializer_list:89:5: note:   template argument deduction/substitution failed:
ch339.cpp:10:31: note:   mismatched types ‘std::initializer_list<_Tp>’ and ‘int*’
for (int *j = begin(row); j!= end(row); ++j )
^
In file included from /usr/include/c++/4.9/string:51:0,
from /usr/include/c++/4.9/bits/locale_classes.h:40,
from /usr/include/c++/4.9/bits/ios_base.h:41,
from /usr/include/c++/4.9/ios:42,
from /usr/include/c++/4.9/ostream:38,
from /usr/include/c++/4.9/iostream:39,
from ch339.cpp:1:
/usr/include/c++/4.9/bits/range_access.h:87:5: note: template<class _Tp, long unsigned int _Nm> _Tp* std::begin(_Tp (&)[_Nm])
begin(_Tp (&__arr)[_Nm])
^
/usr/include/c++/4.9/bits/range_access.h:87:5: note:   template argument deduction/substitution failed:
ch339.cpp:10:31: note:   mismatched types ‘_Tp [_Nm]’ and ‘int*’
for (int *j = begin(row); j!= end(row); ++j )
^
In file included from /usr/include/c++/4.9/string:51:0,
from /usr/include/c++/4.9/bits/locale_classes.h:40,
from /usr/include/c++/4.9/bits/ios_base.h:41,
from /usr/include/c++/4.9/ios:42,
from /usr/include/c++/4.9/ostream:38,
from /usr/include/c++/4.9/iostream:39,
from ch339.cpp:1:
/usr/include/c++/4.9/bits/range_access.h:58:5: note: template<class _Container> decltype (__cont.begin()) std::begin(const _Container&)
begin(const _Container& __cont) -> decltype(__cont.begin())
^
/usr/include/c++/4.9/bits/range_access.h:58:5: note:   template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/range_access.h: In substitution of ‘template<class _Container> decltype (__cont.begin()) std::begin(const _Container&) [with _Container = int*]’:
ch339.cpp:10:31:   required from here
/usr/include/c++/4.9/bits/range_access.h:58:5: error: request for member ‘begin’ in ‘__cont’, which is of non-class type ‘int* const’
/usr/include/c++/4.9/bits/range_access.h:48:5: note: template<class _Container> decltype (__cont.begin()) std::begin(_Container&)
begin(_Container& __cont) -> decltype(__cont.begin())
^
/usr/include/c++/4.9/bits/range_access.h:48:5: note:   template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/range_access.h: In substitution of ‘template<class _Container> decltype (__cont.begin()) std::begin(_Container&) [with _Container = int*]’:
ch339.cpp:10:31:   required from here
/usr/include/c++/4.9/bits/range_access.h:48:5: error: request for member ‘begin’ in ‘__cont’, which is of non-class type ‘int*’
ch339.cpp:10:45: error: no matching function for call to ‘end(int*&)’
for (int *j = begin(row); j!= end(row); ++j )
^
ch339.cpp:10:45: note: candidates are:
In file included from /usr/include/c++/4.9/bits/basic_string.h:42:0,
from /usr/include/c++/4.9/string:52,
from /usr/include/c++/4.9/bits/locale_classes.h:40,
from /usr/include/c++/4.9/bits/ios_base.h:41,
from /usr/include/c++/4.9/ios:42,
from /usr/include/c++/4.9/ostream:38,
from /usr/include/c++/4.9/iostream:39,
from ch339.cpp:1:
/usr/include/c++/4.9/initializer_list:99:5: note: template<class _Tp> constexpr const _Tp* std::end(std::initializer_list<_Tp>)
end(initializer_list<_Tp> __ils) noexcept
^
/usr/include/c++/4.9/initializer_list:99:5: note:   template argument deduction/substitution failed:
ch339.cpp:10:45: note:   mismatched types ‘std::initializer_list<_Tp>’ and ‘int*’
for (int *j = begin(row); j!= end(row); ++j )
^
In file included from /usr/include/c++/4.9/string:51:0,
from /usr/include/c++/4.9/bits/locale_classes.h:40,
from /usr/include/c++/4.9/bits/ios_base.h:41,
from /usr/include/c++/4.9/ios:42,
from /usr/include/c++/4.9/ostream:38,
from /usr/include/c++/4.9/iostream:39,
from ch339.cpp:1:
/usr/include/c++/4.9/bits/range_access.h:97:5: note: template<class _Tp, long unsigned int _Nm> _Tp* std::end(_Tp (&)[_Nm])
end(_Tp (&__arr)[_Nm])
^
/usr/include/c++/4.9/bits/range_access.h:97:5: note:   template argument deduction/substitution failed:
ch339.cpp:10:45: note:   mismatched types ‘_Tp [_Nm]’ and ‘int*’
for (int *j = begin(row); j!= end(row); ++j )
^
In file included from /usr/include/c++/4.9/string:51:0,
from /usr/include/c++/4.9/bits/locale_classes.h:40,
from /usr/include/c++/4.9/bits/ios_base.h:41,
from /usr/include/c++/4.9/ios:42,
from /usr/include/c++/4.9/ostream:38,
from /usr/include/c++/4.9/iostream:39,
from ch339.cpp:1:
/usr/include/c++/4.9/bits/range_access.h:78:5: note: template<class _Container> decltype (__cont.end()) std::end(const _Container&)
end(const _Container& __cont) -> decltype(__cont.end())
^
/usr/include/c++/4.9/bits/range_access.h:78:5: note:   template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/range_access.h: In substitution of ‘template<class _Container> decltype (__cont.end()) std::end(const _Container&) [with _Container = int*]’:
ch339.cpp:10:45:   required from here
/usr/include/c++/4.9/bits/range_access.h:78:5: error: request for member ‘end’ in ‘__cont’, which is of non-class type ‘int* const’
/usr/include/c++/4.9/bits/range_access.h:68:5: note: template<class _Container> decltype (__cont.end()) std::end(_Container&)
end(_Container& __cont) -> decltype(__cont.end())
^
/usr/include/c++/4.9/bits/range_access.h:68:5: note:   template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/range_access.h: In substitution of ‘template<class _Container> decltype (__cont.end()) std::end(_Container&) [with _Container = int*]’:
ch339.cpp:10:45:   required from here
/usr/include/c++/4.9/bits/range_access.h:68:5: error: request for member ‘end’ in ‘__cont’, which is of non-class type ‘int*’
shell returned 1
Press ENTER or type command to continue

row的类型被推导为int*。这意味着,就像任何其他int*一样,编译器根本不知道它指向的数组有多大,甚至不知道它是指向数组第一个元素的指针。当数组衰减为指向其第一个元素的指针时,所有这些信息都会丢失。

如果你使用类似的东西

for (auto& row : ia) // <-- NOTE: row is now a reference
for (int* j = std::begin(row); j != std::end(row); ++j)
std::cout << *j << 'n';

row的类型将被推导为int (&)[4]:对4个ints的阵列的引用。长度信息被保留,因此std::beginstd::end具有它们所需的信息。


PS:注意:内部使用std::beginstd::end的工作范围,因此以上内容可以更简洁地写成

for (auto& row : ia)
for (auto j : row)
std::cout << j << 'n';

最新更新