首页 > 解决方案 > 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++arraysranged-loops

解决方案


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) {
        // ...
    }
}

推荐阅读