基于范围的普通数组的工作原理如何?

Pau*_*nta 76 c++ arrays foreach c++11

在C++ 11中,您可以使用基于范围的语言for,它可以充当foreach其他语言.它甚至适用于普通的C数组:

int numbers[] = { 1, 2, 3, 4, 5 };
for (int& n : numbers) {
    n *= 2;
}
Run Code Online (Sandbox Code Playgroud)

怎么知道什么时候停止?它是否仅适用于已在相同范围内声明的静态数组for?你会如何for在动态数组中使用它?

Joh*_*itb 52

它适用于任何类型为数组的表达式.例如:

int (*arraypointer)[4] = new int[1][4]{{1, 2, 3, 4}};
for(int &n : *arraypointer)
  n *= 2;
delete [] arraypointer;
Run Code Online (Sandbox Code Playgroud)

有关更详细的说明,如果传递到右侧的表达式的类型:是数组类型,则循环从迭代ptrptr + size(ptr指向数组的第一个元素,即数组size的元素计数).

这是相对于用户定义的类型,通过该工作查找beginend作为成员如果传递类对象或(如果没有成员称为那样)非成员函数.这些函数将产生开始和结束迭代器(分别指向最后一个元素和序列的开头).

这个问题清除了为什么存在这种差异.

  • 我认为问题是_how_它是否有效,而不是_when_它是否有效 (8认同)
  • @JohannesSchaub:我认为这里的"如何"问题是你究竟如何获得数组类型对象的大小(因为指针与数组混淆,几乎每个人都不知道数组的大小*是*可供程序员使用.) (7认同)
  • @Dennis no在马德里决定改变这一点,并支持开始和结束成员.不赞成开始和结束成员导致难以避免的含糊不清. (3认同)

psu*_*sur 32

我认为这个问题最重要的部分是,C++如何知道数组的大小(至少我想知道这个问题时).

C++知道数组的大小,因为它是数组定义的一部分 - 它是变量的类型.编译器必须知道类型.

由于C++ 11 std::extent可用于获取数组的大小:

int size1{ std::extent< char[5] >::value };
std::cout << "Array size: " << size1 << std::endl;
Run Code Online (Sandbox Code Playgroud)

当然,这没有多大意义,因为你必须在第一行显式提供大小,然后在第二行中获得.但你也可以使用decltype然后它变得更有趣:

char v[] { 'A', 'B', 'C', 'D' };
int size2{ std::extent< decltype(v) >::value };
std::cout << "Array size: " << size2 << std::endl;
Run Code Online (Sandbox Code Playgroud)

  • 这确实是我最初问的问题.:) (4认同)

小智 17

根据最新的C++工作草案(n3376),ranged for语句等同于以下内容:

{
    auto && __range = range-init;
    for (auto __begin = begin-expr,
              __end = end-expr;
            __begin != __end;
            ++__begin) {
        for-range-declaration = *__begin;
        statement
    }
}
Run Code Online (Sandbox Code Playgroud)

所以它知道如何for使用迭代器以常规循环的方式停止.

我想你可能正在寻找类似下面的东西,以提供一种方法来使用上面的语法与只包含指针和大小的数组(动态数组):

template <typename T>
class Range
{
public:
    Range(T* collection, size_t size) :
        mCollection(collection), mSize(size)
    {
    }

    T* begin() { return &mCollection[0]; }
    T* end () { return &mCollection[mSize]; }

private:
    T* mCollection;
    size_t mSize;
};
Run Code Online (Sandbox Code Playgroud)

然后可以使用此类模板创建一个范围,您可以使用新范围的语法迭代该范围.我使用它来运行场景中的所有动画对象,该场景使用只返回指向数组的指针和大小作为单独值的库导入.

for ( auto pAnimation : Range<aiAnimation*>(pScene->mAnimations, pScene->mNumAnimations) )
{
    // Do something with each pAnimation instance here
}
Run Code Online (Sandbox Code Playgroud)

在我看来,这种语法比你使用的语法std::for_each或普通for循环更清晰.