gpt4 book ai didi

c++ - 内部函数的范围错误

转载 作者:IT老高 更新时间:2023-10-28 22:32:49 26 4
gpt4 key购买 nike

我在使用 C++ 中的 ranged for 时遇到了一点麻烦。我正在尝试使用它在 int 数组 (int[]) 上显示元素,当我在主函数上执行此操作时,它工作得非常好,例如:

int main(int argc, char const *argv[]) {

int v[] = {3, 4, 6, 9, 2, 1};

for (auto a : v) {
std::cout << a << " ";
}
std::cout << std::endl;

return 0;
}

我得到了我想要的和预期的输出:

3 4 6 9 2 1

但是当我尝试在函数内部使用 ranged for 时,事情变得有点奇怪,例如,我遇到了这段代码的问题:

void printList(int *v);

int main(int argc, char const *argv[]) {

int v[] = {3, 4, 6, 9, 2, 1};

printList(v);

return 0;
}

void printList(int *v) {
for (auto a : v) {
std::cout << a << " ";
}
std::cout << std::endl;
}

对我来说,这与我在 main 中所做的相同,并且使用正常的 for 完全可以正常工作。奇怪的错误如下:

p4.cpp: In function ‘void printList(int*)’:
p4.cpp:15:17: error: ‘begin’ was not declared in this scope
for (auto a : v) {
^
p4.cpp:15:17: note: suggested alternative:
In file included from /usr/include/c++/5/string:51:0,
from /usr/include/c++/5/bits/locale_classes.h:40,
from /usr/include/c++/5/bits/ios_base.h:41,
from /usr/include/c++/5/ios:42,
from /usr/include/c++/5/ostream:38,
from /usr/include/c++/5/iostream:39,
from p4.cpp:1:
/usr/include/c++/5/bits/range_access.h:105:37: note: ‘std::begin’
template<typename _Tp> const _Tp* begin(const valarray<_Tp>&);
^
p4.cpp:15:17: error: ‘end’ was not declared in this scope
for (auto a : v) {
^
p4.cpp:15:17: note: suggested alternative:
In file included from /usr/include/c++/5/string:51:0,
from /usr/include/c++/5/bits/locale_classes.h:40,
from /usr/include/c++/5/bits/ios_base.h:41,
from /usr/include/c++/5/ios:42,
from /usr/include/c++/5/ostream:38,
from /usr/include/c++/5/iostream:39,
from p4.cpp:1:
/usr/include/c++/5/bits/range_access.h:107:37: note: ‘std::end’
template<typename _Tp> const _Tp* end(const valarray<_Tp>&);
^

我想知道为什么会发生这个错误,我认为这可能发生的原因是,因为我是数组的指针表示,所以丢失了一些信息,但是为什么会丢失这些信息我不知道.有人深入了解吗?我也在寻找这种替代解决方案:

template <std::size_t len>
void printList(int (&v)[len]) {
for (int a : v) {
std::cout << a << " ";
}
std::cout << std::endl;
}

效果很好,但如果我使用类似的东西:

template <std::size_t len>
void printList(int (&v)[len]);

int main(int argc, char const *argv[]) {
.........
}

void printList(int (&v)[len]) {
for (int a : v) {
std::cout << a << " ";
}
std::cout << std::endl;
}

我得到错误:

p4.cpp:15:25: error: ‘len’ was not declared in this scope
void printList(int (&v)[len]) {
^
p4.cpp: In function ‘void printList(...)’:
p4.cpp:16:16: error: ‘v’ was not declared in this scope
for (int a : v) {

为什么会这样?有没有不使用模板格式的简单解决方案?有没有办法可以使用参数作为传递数组和隐式大小信息的方式?

最佳答案

基于范围的 for 循环本质上只是语法糖,即从 cppreference 检索到

for ( range_declaration : range_expression ) loop_statement (until C++20)

for ( init-statement(optional) range_declaration : range_expression ) loop_statement (since C++20)

在功能上等同于:

{
auto && __range = range_expression ;
for (auto __begin = begin_expr, __end = end_expr;
__begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}

或者,如果您使用 c++17 或更高版本,这实际上允许 __begin 使用不同的类型和 __end .

{
init-statement // only since C++20
auto && __range = range_expression ;
auto __begin = begin_expr ;
auto __end = end_expr ;
for ( ; __begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}

在哪里 begin_exprend_expr形成如下

  1. If range_expression is an expression of array type, then begin_expr is __range and end_expr is (__range + __bound), where __bound is the number of elements in the array (if the array has unknown size or is of an incomplete type, the program is ill-formed)

  2. If range_expression is an expression of a class type C that has a member named begin and/or a member named end (regardless of the type or accessibility of such member), then begin_expr is __range.begin() and end_expr is __range.end();

  3. Otherwise, begin_expr is begin(__range) and end_expr is end(__range), which are found via argument-dependent lookup (non-ADL lookup is not performed).


让我们看看这如何适用于您的案例:

在第一种情况下 v肯定是数组类型的表达式,或者确切地说是 int(&)[6] 类型的表达式, 所以我们使用案例 (1) 其中 __bound = 6等(为简洁起见,省略全部扣除的替代品)

在第二种情况下,当你有一个函数时,v类型为 int*并且由于它不是数组类型,指针也没有成员,我们默认为使用 ADL 的情况 (3)确定要调用的函数 begin(__range)它不会产生指针类型的结果,因此编译器会提示 error: ‘begin’ was not declared in this scope .

第三种情况,你在尝试定义函数模板时出错printList .您必须保留 template<...>您包含在声明中的部分,否则它只是一个函数的定义。这就是为什么编译器会告诉你 error: ‘len’ was not declared in this scope .因此,正确且有效的代码是

template <std::size_t len>
void printList(int (&v)[len]);

int main(int argc, char const *argv[]) {
int v[] = {3, 4, 6, 9, 2, 1};
printList(v);
return 0;
}

template <std::size_t len>
void printList(int (&v)[len]) {
for (int a : v) {
std::cout << a << " ";
}
std::cout << std::endl;
}

其他答案已经在提议使用不同的容器类型,例如 std::array<int, 6>提出一个有效的观点。一定要看看它们,尤其是使用大括号初始化,您几乎可以免费升级到它们。

关于c++ - 内部函数的范围错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40791235/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com