- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我是 C++ 的新手。
int*
?&
有什么用?.
int arr[10][3];
for (auto &i : arr)
{
for (auto j : i)
{
//sth
}
}
最佳答案
首先我们需要知道int arr[10][3];
的具体数据类型.它是一个由 10 个数组组成的 数组,每组 3 个 int
.
循环通常迭代多维容器的一个维度,例如
for(int i = 0; i < 10; ++i)
{
for(int j = 0; j < 3; ++j)
{
arr[i][j] = 0;
}
}
第一个循环遍历 10 的数组 X
,第二个循环然后遍历 X
,这是一个数组,包含 3 int
.
下一步是显式使用这个 X
在代码中:
for(int i = 0; i < 10; ++i)
{
int (&x)[3] = arr[i]; // you won't see this syntax often
for(int j = 0; j < 3; ++j)
{
int &elem = x[j];
elem = 0;
}
}
行int (&x)[3]
声明对 数组 3 int
的引用,这是访问多维数组第一层arr
的结果.
我们也可以使用迭代器来写这个例子:
for(int (*px)[3] = arr; px != arr+10; ++px)
{
// `px` is a _pointer to an array of 3 `int`_
// `*px` then is an _array of 3 `int`_
for(int *pelem = *px; pelem != (*px)+3; ++pelem)
{
*pelem = 0;
}
}
请注意,我在这里使用的功能是将数组转换为指向其第一个元素的指针。这称为衰减:一个数组是/可以衰减到一个指针(指向该数组的第一个元素),例如
int my_arr[3];
int *p = my_arr; // `p` now points to the first element of `my_arr`
p = &my_arr[0]; // equivalent
对于多维数组,这变成了
int arr[10][3];
int (*p)[3]; // a pointer to an _array of 3 `int`_
p = arr; // `p` now points to the first element of `arr`, i.e.
// the first _array of 3 `int`_
最后但同样重要的是,对于多维数组,也可以这样写:
for(int *pelem = arr[0]; pelem != arr[0]+10*3; ++pelem)
{
*pelem = 0;
}
但这只适用于多维数组,因为它们在内存中是连续布局的,并且多维数组的内存布局是指定的。
这对于像 vector<vector<int>>
这样的容器是不可能的, 尽管
vector<int> v = {1,2,3,4,5};
for(int* i = &v[0]; i != &v[0] + 5; ++i)
{
*i = 0;
}
格式正确,没有未定义的行为。
相同的逻辑现在适用于基于范围的 for 循环:
for(int (&x)[3] : arr)
{
for(int &elem : x)
{
elem = 0;
}
}
拥有基于范围的 for 循环的全部意义在于摆脱显式迭代器。 int*
就是这样一个迭代器,所以没有必要使用基于范围的 for 循环遍历 int*
海事组织。
how does this nested range-based for perform, deeply?
C++ 语言标准在 [stmt.ranged] 中定义了基于范围的 for 语句如下(注意我已经简化了一点):
for (
for-range-declaration:
expression)
statement
决议为:
{
for ( auto __begin = /*begin-expr*/,
__end = /*end-expr*/;
__begin != __end;
++__begin )
{
/*for-range-declaration*/ = *__begin;
/*statement*/
}
}
for-range-declaration 和 statement 本质上是从未解析的基于范围的 for 循环中复制粘贴的。其余的(begin-expr、end-expr)有些复杂,这里是一个简化版本:
{
using std::begin;
using std::end;
for ( auto __begin = begin(/*expression*/),
__end = end(/*expression*/);
__begin != __end;
++__begin )
{
/*for-range-declaration*/ = *__begin;
/*statement*/
}
}
我的基于范围的 for 循环示例是从
for(int (&x)[3] : arr)
{
/*statements*/
}
到
{
using std::begin;
using std::end;
for ( auto __begin = begin(arr),
__end = end(arr);
__begin != __end;
++__begin )
{
int (&x)[3] = *__begin;
/*statements*/
}
}
或者,通过解析 begin
/end
调用:
{
for ( int (*__begin)[3] = arr,
__end = arr + 10;
__begin != __end;
++__begin )
{
int (&x)[3] = *__begin; // (A)
/*statements*/
}
}
标有 (A)
的行还显示了为什么 &
在一个例子中 for (int x[3] : arr)
是必要的:
int arr[10][3];
int (&x)[3] = arr[0]; // well-formed
int x [3] = arr[0]; // ill-formed for arrays
不允许直接分配原始/C 风格的数组,您可能从类似的示例中了解到
int my_arr[10];
int my_sec_arr[10] = my_arr; // not legal, ill-formed
这就是您必须使用引用的原因。
使用标准库的 std::array
等其他容器,可以避免引用:
std::array<int, 10> my_arr;
std::array<int, 10> my_sec_arr = my_arr; // well-formed
但是赋值意味着复制,所以必须复制整个数组;而此处的引用不需要复制。
作为Yakk指出in the comments ,这并不是 &
的原因在你的例子中是必要的for (auto &i : arr)
, 作为 auto &i = arr[0];
解析为 int (*i)[3] = arr[0];
.但如您所见,auto
将数组衰减为指针,因此您的第二次迭代失败:
for(auto i : arr)
{
// type of `i` now is _pointer to an array of 3 `int`_
for(auto j : i) // can't iterate over a pointer: what are the boundaries?
{
/* ... */
}
}
更精确一点:您可以遍历一个数组,因为编译器知道数组中有多少个元素;它是类型的一部分,例如3 的数组 int
,并且类型是编译器已知的。
对于指针,编译器不知道指针是指向单个元素还是指向元素数组,在后一种情况下它不知道该数组有多大。任何情况下的类型都是,例如指向int
的指针:
int my_arr[10];
int my_int;
int *p;
p = my_arr;
p = &my_int;
p = new int[25];
关于c++ - 为什么在嵌套的基于范围的 for 循环中引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17907913/
所以我试图设置“内容”类的高度,但它似乎不起作用。我对嵌套 DIV 非常陌生,我已经尝试了我在谷歌搜索中发现的修复程序,但似乎没有任何效果。帮助?
好的,所以我一直在四处寻找,但找不到这个问题的答案。但是,我需要将一个 View 嵌套在另一个 View 中。 我有一个 $layout 正在使用我拥有的 default.layout Blade 文
好的,所以我一直在四处寻找,但找不到这个问题的答案。但是,我需要将一个 View 嵌套在另一个 View 中。 我有一个 $layout 正在使用我拥有的 default.layout Blade 文
基本上,我的问题很简单,但它需要知道 Struts 1.1 并且还活着的人。 我尝试构建的伪代码看起来像这样: IF element.method1 = true THEN IF element
我正在尝试将 Excel 嵌套 IF 语句转换为代码语言,但我不确定我是否正确执行此操作,希望能得到一些帮助 这是Excel语句: =IF(D3="Feather",IF(OR(I3>1000,R3=
如果我们创建两个或三个评论并对其进行多次回复,则“有用”链接在单击时会导致问题,它会对具有相同编号的索引执行 ng-click 操作,从而显示具有相同索引的所有文本。如何解决此嵌套问题,以便在单击链接
我在项目中使用Scala,想与Stripe集成,但它只提供Java API。例如,要创建 session ,我使用: val params = new util.HashMap[String, Any
以下代码有一个 Div,其中连续包含四个较小的 Div。四个 Div 中的每一个还包含一个较小的 Div,但此 Div 未显示。我尝试了各种显示和位置组合,看看 div 是否会出现。 classGoa
我在这里有一个问题,循环是: for (i=0; i < n; ++i) for (j = 3; j < n; ++j) { ...
我正在尝试编写代码来显示具有奇数宽度的形状。形状完成后,将其放置在外部形状内。用户将能够输入用于形状的字符和行数。我希望生成一个形状,并通过 for 循环生成一个外部形状。 ***** .
$(".globalTabs").each(function(){ var $globalTabs = $(this); var parent = $globalTabs.parent
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 9 年前。 Improve th
所以我在这个问题上遇到了一些麻烦,因为变量 i。我只是不确定在第二个 while 循环中如何处理它。对于我的外循环,我知道它将运行 log_4(n^2) 次迭代。对于内部 while 循环,我计算的迭
我似乎找不到在枚举上应用多个 if/then 逻辑的工作方式。 anyOf 不应用条件逻辑,而是表示如果其中任何一个匹配则很好。 allOf 再次不应用条件逻辑,而是测试属性/必填字段的超集。 这是一
如何访问 ReaderT 的内部 monad。 在我的例子中,我有类型: newtype VCSSetupAction a = VCSSetupAction (ReaderT (Maybe VCSCo
这个问题在这里已经有了答案: Add leading zeroes/0's to existing Excel values to certain length (7 个回答) 7年前关闭。 我正在寻
我已经绑定(bind)了很多 AND/OR 函数的组合并且没有运气。 这是我需要创建的: 在 B 列中,我有公司 ID,范围从两个数字字符到六个数字字符。 我需要在 B 列中的每个公司 ID 之前的每
我是 VBA 新手,在尝试编写的宏中使用 If 语句时遇到了一些困难。每个月我都会收到一份 Excel 报告,其中列出了我们公司的哪些员工执行了某些任务。我正在编写的宏旨在将每个员工的数据复制并粘贴到
如果在 B 列中找到单元格 A1 中的值,则使用文本 321 填充除非在 C 列中找到单元格 A1 中的值,在这种情况下填充文本 121反而。如果单元格 A1 的内容不在 B 列或 C 列中,则使用
我有几十万个地址。其中一些在整数之后有粒子。如 4356 A Horse Avenue , 其他格式正常4358 Horse Avenue .有些有“A”,有些有“B”。我正在尝试删除整数和粒子之间的
我是一名优秀的程序员,十分优秀!