无法识别的基于范围的循环?

use*_*072 9 c++ arrays pointers for-loop range

为什么这段代码:

void printarray(int array[]) {
    for (int x: array) {
        std::cout << x << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

生成此编译时错误?

error: 'begin' was not declared in this scope
    for (int x: array) {
Run Code Online (Sandbox Code Playgroud)

我对基于范围的for循环的错误是什么?

Nat*_*ica 13

你的问题是它array实际上不是一个数组.当你写作

void printarray(int array[])
Run Code Online (Sandbox Code Playgroud)

它是一样的

void printarray(int* array)
Run Code Online (Sandbox Code Playgroud)

由于在没有附加大小参数的情况下无法确定指针指向的元素数量,因此无法将其与基于范围的for循环一起使用.

您需要做的是通过引用传递数组,以便数组不会衰减成指针.如果您知道阵列的确切大小,那么您可以使用

void printarray(int (&array)[size_you_want_here])
Run Code Online (Sandbox Code Playgroud)

如果你想让函数更通用,那么它可以使用不同大小的数组,那么你可以使用像这样的模板

template<std::size_t N>
void printarray(int (&array)[N])
Run Code Online (Sandbox Code Playgroud)

在上述两种情况下,您现在都有一个实际的数组而不是指针,因此您可以将它与基于范围的for循环一起使用.

另请注意,我们可以使用完全通用的功能

template<typename T, std::size_t N>
void printarray(T (&array)[N]) {
    for (auto&& x : array) {
        std::cout << x << "\n";
    }
}
Run Code Online (Sandbox Code Playgroud)

您还会注意到我std::endl改为"\n".通常,您不希望使用endlflush()在流上显式调用.通常"\n"就是你需要的所有东西,如果输出仍然没有刷新,那么你可以打电话给flush()自己.


Vla*_*cow 5

当数组作为函数的参数传递时,它会隐式转换为指向其第一个元素的指针.声明数组的参数也会调整为指针.

例如,这些函数声明

void printarray( int array[100] );
void printarray( int array[10] );
void printarray( int array[] );
Run Code Online (Sandbox Code Playgroud)

声明相同的一个函数和等价物

void printarray( int *array );
Run Code Online (Sandbox Code Playgroud)

因此,您需要将数组的大小传递给函数,例如

void printarray( const int array[]. size_t n ) 
{
    for ( size_t i = 0; i < n; i++ ) 
    {
        std::cout << a[i] << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

例如,您可以专门为通过引用传递的数组编写模板函数

template <size_t N>
void printarray( const int ( &array )[N] ) 
{
    for ( int x : array) 
    {
        std::cout << x << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

要么

template <typename T, size_t N>
void printarray( const T ( &array )[N] ) 
{
    for ( auto x : array) 
    {
        std::cout << x << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,与之前的函数相比,它有一个缺点,因为不同大小的数组是不同的类型,编译器将从模板生成尽可能多的函数,因为您将使用该函数的许多不同类型的数组.

您可以使用标准算法std::copystd::for_each输出数组.

例如

#include <iostream>
#include <algorithm>
#include <iterator>

int main() 
{
    int array[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

    std::copy( std::begin( array ), std::end( array ), 
               std::ostream_iterator<int>( std::cout, "\n" ) );

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用std::array具有适当成员函数的标准类,begin并且end由基于for语句的范围使用.例如

#include <iostream>
#include <array>

const size_t N = 10;

void printarray( const std::array<int, N> &array )
{
    for ( int x : array ) std::cout << x << std::endl;
}   

int main() 
{
    std::array<int, N> array = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

    printarray( array );

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是在这种情况下,如果要输出std::array具有不同数量或类型的元素的类对象,则还需要编写模板函数.

例如

#include <iostream>
#include <array>

template <typename T, size_t N>
void printarray( const std::array<T, N> &array )
{
    for ( auto x : array ) std::cout << x << std::endl;
}   

int main() 
{
    std::array<int, 10> array1 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

    printarray( array1 );

    std::array<char, 10> array2 = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J' };

    printarray( array2 );

    return 0;
}
Run Code Online (Sandbox Code Playgroud)