c++ - c++ 在具有多向数组的范围循环中初始化变量
问题描述
我是第一次学习c++(我是从python过渡的)
当我尝试使用多维数组处理和编译范围循环时,我看到了一些奇怪的行为。考虑以下情况:
#include <iostream>
#include <typeinfo>
int array[2][3]
for (dataType row : array) { std::cout << typeid(row).name(); }
如果 dataType 为 const int* row,则 row 成为指针(其元素)不能被修改。这是意料之中的。
for (const int* row : array) { std::cout << typeid(row).name(); }
输出:int const * __ptr64
如果 dataType 为 const auto row,则 row 成为可以修改的指针。无论您是否尝试修改代码中的行,编译器都会忽略您将行设为常量变量的请求。
for (const auto row : array) { std::cout << typeid(row).name(); }
输出:int * __ptr64
在上述情况下,我可以修改行的内容而不会出现任何错误。
如果在 auto 之后添加星号,您现在将获得一个常量变量。您需要同时输入 const 并加上星号以使其保持不变。
for (const auto* row : array) { std::cout << typeid(row).name(); }
输出:int const * __ptr64
现在,如果我们使用 & 运算符而不是星号,则行将变为大小为 3 的数组。在这里,& 没有修改地址或任何东西,我找不到强制编译器复制内部数组并放入的方法它在新地址的行内。这只是使使用嵌套范围循环变得更容易。
for (auto& row : array) { std::cout << typeid(row).name(); }
输出:int [3]
但是现在,我不能手动告诉编译器创建一个数组。输入类似 int row[3] 的内容甚至不会被编译。获取数组的唯一方法是使用 auto&
for (int row[3] : array) { std::cout << typeid(row).name(); }
CompilerError E0144:“int*”类型的值不能用于初始化“int[3]”类型的实体
for (int& row[3] : array) { cout << typeid(n).name(); }
CompilerError E0144:“int*”类型的值不能用于初始化“int[3]”类型的实体
CompilerError E0251:不允许引用数组
我喜欢在我的代码中使用嵌套的范围循环,这是我在使用 python 时养成的习惯。它使代码更容易编写、阅读并且更不容易出错。为了可读性和调试,我想要一种方法来强制我的编译器将行初始化为数组,而不是使用 auto& 并让编译器决定它想要数组的数据类型。
另外,我想要一种在另一个地址获取行的深层副本的方法,这样我就可以在不更改原始数组的情况下修改循环内的内容。对于一维循环,省略 & 运算符将在不同地址复制数据,但对于多维数组,它始终是相同的地址。
当您使用 const auto 而不是 const auto* 进行初始化时,最好知道发生了什么。添加星号对编译器有何重要意义?
解决方案
C 数组是不可复制的,并且引用类型的语法很奇怪/丑陋。
我建议使用std::array
它是一个很好的替代品。
std::array<std::array<int, 3>, 2> array;
for (/*const*/ std::array<int, 3> /*&*/ row : array) {
for (int /*&*/ e : row) {
// ...
}
}
for (/*const*/ auto /*&*/ row : array) {
for (auto /*&*/ e : row) {
// ...
}
}
C-array 只允许通过引用传递(否则衰减到指针)
int array[2][3];
for (/*const*/ int (&row)[3] : array) {
for (int /*&*/ e : row) {
// ...
}
}
for (/*const*/ auto & row : array) {
for (auto /*&*/ e : row) {
// ...
}
}
推荐阅读
- c# - 将应用程序上传到弹性 beantalk AWS 并使 ebextensions 文件选择模式发布或测试
- python - 从 Keras 的 BatchNormalization 派生的类的用途不明确
- python - 如何从 Python 脚本创建日志文件并保存所有运行日志
- etl - 数据仓库和原子性很少共存
- c++ - ESP32 FreeRTOS 从另一个任务中删除一个任务
- azure-functions - 具有 Azure 函数调用完成阶段的数据工厂
- javascript - 为什么我的三元运算符会破坏我的登录路由?
- nginx - 部署的角度项目,如果路由更改,Nginx 显示 404 错误
- python - Keras tokenizer.fit_on_texts 在做什么?
- reactjs - 不断地对 axios 帖子做出反应