使用C ++ 11的begin()和end()函数通过参数确定数组维度

时间:2016-03-05 19:50:49

标签: c++ arrays c++11

所以我目前正在学习C ++(以前的Java和JavaScript经验),就我而言,你不能像在Java中那样在C ++中传递一个数组作为参数。但是您可以将指针传递给数组中的第一个元素。所以我可以迭代这样的数组:

bool occurs(int* arrInt, int length, int sought, int& occurrences)
{
    for (int i = 0; i <= length; ++i)
    {
        if (arrInt[i] == sought)
            occurrences++;
    }

    // if occurences > 0 return true, else false
    return occurrences;
}

整个函数应该基本上返回一个布尔值,告诉我是否在数组(sought)中找到了给定的int(arrInt)。我也通过参考(occurrences)提供一个小计数器。 但是我的错误是length参数。 C ++ 11提供了那些花哨的std :: begin / cbegin()和std :: end / cend()函数来获取数组的最后一个元素的第一个和一个:

int arr[] = {1,2,3,4} // arr is basically a pointer to an int, just as the
                      // function parameter of ocurs(int*,int,int,int&)
auto end = std::end(arr); // end points to one past last element

但为什么我不能使用arrInt参数作为该函数的参数?然后我可以摆脱长度参数:

bool occurs(int* arrInt, int sought, int& occurences)
{
    for (auto it = std::begin(arrInt); it != std::end(arrInt); ++it)
    {
        if (*it == sought)
            occurences++;
    }

    // if occurences > 0 return true, else false
    return occurences;
}

我在这里错过了一个主要概念吗?提前致谢

2 个答案:

答案 0 :(得分:8)

在你的第一个例子中:

int arr[] = {1,2,3,4} // arr is basically a pointer to an int, just as the
                      // function parameter of ocurs(int*,int,int,int&)
auto end = std::end(arr); // end points to one past last element

arr &#34;基本上是指向int&#34;的指针。 arr的类型为int[4]。请注意,长度是类型的一部分。因此,编译器可以轻松确定哪一个过去的最后一个元素&#34;是。只需添加长度。

如果混淆可能是arr 可兑换(您有时会听到衰变int*。但它并不仅仅是一个指针。

在你的第二个例子中:

bool occurs(int* arrInt, int sought, int& occurences)
{
    for (auto it = std::begin(arrInt); it != std::end(arrInt); ++it) {
        ...
    }
    ...
}

arrInt 只是一个指针。因此,您怎么知道end()在哪里?这里没有任何信息。这就是你需要额外长度参数的原因。

你可以传入完整的数组,但你必须通过引用来做(你不能按值传递数组,谢谢C!)。要做到这一点,你必须使它成为一个功能模板:

template <size_t N>
bool occurs (int (&arrInt)[N], int sought, int& occurrences) {
    ...
}

此处,arrInt是一个数组 - 其长度以类型(N)编码。所以你可以写std::end(arrInt)

occurs()基本上是重写std::count,所以你可以改用它:

int arr[] = {1, 2, 3, 3, 8};
int occurrences = std::count(std::begin(arr), std::end(arr), 3); // yields 2

或者,更简单一点,使用std::vector<int>

答案 1 :(得分:1)

首先,请注意数组不是指针。所以在这个示例代码中:

int arr[] = {1,2,3,4} // arr is basically a pointer to an int, just as the
                      // function parameter of ocurs(int*,int,int,int&)

......评论完全没错。

但是,在C和C ++中,在期望指针的上下文中,数组类型表达式衰减为指针类型,指向第一个项目的指针。不是这种上下文的示例是通过引用传递数组的位置。另一个例子是它被用作sizeof的参数。

arrInt声明为

int* arrInt

它只是一个指针,没有关于它是指向单个int还是指向数组中某个位置的信息,所以

std::end(arrInt)

无法推断出数组大小。通常它会从参数的数组类型中推断出它。或者来自容器的sizeend成员(未实现其实施方式,并且可通过多种方式获取相同的信息)。

一种可能性是改变您的功能设计,例如将其更改为接受两个指针(或一般迭代器),如std::find

另一种可能性是在你的函数中使用std::find

你可以这样做,因为给定一个开始指针和一个数组大小,你可以简单地计算数组的过去结束指针,用作std::find的参数。