C++ 不能在数组上使用 .begin() 或 .end()

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14595285/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 18:29:22  来源:igfitidea点击:

Cannot use .begin() or .end() on an array

c++arrayspointersc++11iterator

提问by Sal Rosa

The error reads:

错误如下:

request for member 'begin', 'end' in 'arr' which is non class type int[5], unable to deduce from expression error.

请求非类类型 int[5] 的 'arr' 中的成员 'begin'、'end',无法从表达式错误中推断出。

My code:

我的代码:

#include <iostream>
using namespace std;

int main()
{
    int * mypointer;

    int arr[5] = {1,3,5,7,9};

    mypointer = arr;

    for(auto it = arr.begin(); it != arr.end(); ++it) {
        cout<<*mypointer<<endl;

        mypointer++;
    }

    return 0;
}

回答by GManNickG

Arrays have no member functions as they aren't a class type. This is what the error is saying.

数组没有成员函数,因为它们不是类类型。这就是错误所说的。

You can use std::begin(arr)and std::end(arr)from the <iterator>header instead. This also works with types that dohave .begin()and .end()members, via overloading:

您可以从标题中使用std::begin(arr)和。这也适用于该类型有和成员,通过超载:std::end(arr)<iterator>.begin().end()

#include <array>
#include <vector>

#include <iterator>

int main()
{
    int c_array[5] = {};
    std::array<int, 5> cpp_array = {};
    std::vector<int> cpp_dynarray(5);

    auto c_array_begin = std::begin(c_array); // = c_array + 0
    auto c_array_end = std::end(c_array);     // = c_array + 5

    auto cpp_array_begin = std::begin(cpp_array); // = cpp_array.begin()
    auto cpp_array_end = std::end(cpp_array);     // = cpp_array.end()

    auto cpp_dynarray_begin = std::begin(cpp_dynarray); // = cpp_dynarray.begin()
    auto cpp_dynarray_end = std::end(cpp_dynarray);     // = cpp_dynarray.end()
}

回答by user1329482

For a standard fixed-length C array, you can just write

对于标准的固定长度的 C 数组,你可以只写

int c_array[] = {1,3,5,7,9}, acc = 0;

for (auto it : c_array) {
    acc += it;
}

The compiler does the behind-the-scenes work, eliminating the need to create all those begin and end iterators.

编译器执行幕后工作,无需创建所有这些开始和结束迭代器。

回答by Code-Apprentice

In C++, arrays are notclasses and therefore do not have anymember methods. They do behave like pointers in some contexts. You can take advantage of this by modifying your code:

在 C++ 中,数组不是类,因此没有任何成员方法。在某些情况下,它们的行为确实像指针。您可以通过修改代码来利用这一点:

#include <iostream>
using namespace std;

int main()
{
    int * mypointer;

    const int SIZE = 5;
    int arr[SIZE] = {1,3,5,7,9};

    mypointer = arr;

    for(auto it = arr; it != arr + SIZE; ++it) {
        cout<<*mypointer<<endl;

        mypointer++;
    }

    return 0;
}

Of course, this means that mypointerand itboth contain the same address, so you don't need both of them.

当然,这意味着mypointerit都包含相同的地址,因此您不需要同时使用它们。

回答by Herpin the Derps

One thing I'd like to point out for you is that you really don't have to maintain a separate int* to use in dereferencing the array elements, apart from the whole member thing others have well pointed out.

我想为您指出的一件事是,除了其他人已经很好地指出的整个成员之外,您真的不必维护单独的 int* 来取消引用数组元素。

Using a more modern approach, the code is both more readable, as well as safer:

使用更现代的方法,代码更易读,也更安全:

#include <iostream>
#include <algorithm>
#include <array>
#include <iterator>
using namespace std;

int main()
{
    std::array<int, 5> cpp_array{1,3,5,7,9};

    // Simple walk the container elements.
    for( auto elem : cpp_array )
        cout << elem << endl;

    // Arbitrary element processing on the container.
    std::for_each( begin(cpp_array), end(cpp_array), [](int& elem) {
        elem *= 2;      // double the element.
        cout << elem << endl;
    });
}

Using the lambda in the second example allows you to conveniently perform arbitrary processing on the elements, if needed. In this example, I'm just showing doubling each element, but you can do something more meaningful within the lambda body instead.

如果需要,在第二个示例中使用 lambda 可以方便地对元素执行任意处理。在这个例子中,我只是展示了将每个元素加倍,但你可以在 lambda 主体中做一些更有意义的事情。

Hope this makes sense and helps.

希望这是有道理的并有所帮助。

回答by Jeff Moellmer

Perhaps here is a cleaner way to do it using templates and lambdas in c++14:

也许这里是在 c++14 中使用模板和 lambdas 的一种更简洁的方法:

Define:

定义:

template<typename Iterator, typename Funct>
void my_assign_to_each(Iterator start, Iterator stop, Funct f) {
    while (start != stop) {
        *start = f();
        ++start;
    }
}

template<typename Iterator, typename Funct>
void my_read_from_each(Iterator start, Iterator stop, Funct f) {
    while (start != stop) {
        f(*start);
        ++start;
    }
}

And then in main:

然后在主要:

int x[10];
srand(time(0));
my_assign_to_each(x, x+10, [] () -> int { int rn{}; rn = rand(); return rn; });
my_read_from_each(x, x+10, [] (int value) { std::cout << value << std::endl; });

int common_value{18};
my_assign_to_each(x, x+10, [&common_value] () -> int { return common_value; });
my_read_from_each(x, x+10, [] (int value) { std::cout << value << std::endl; });

回答by Roshan Mehta

Quite late but I think it's worth to mention that:

很晚了,但我认为值得一提的是:

void findavgTime(int n)
{
    int wt1[n];
    fill_wt(wt1,n); //Any method that puts the elements into wt1
    int wt2[3];
    int sum  = accumulate(begin(wt1), end(wt1), 0); // Fails but wt2[3] will pass. Reason: variable-sized array type ‘int [n]' is not a valid template argument)
}