将连续数组传递给函数时,传递指针和大小,还是传递开始指针和结束指针更可取?[已结束]

When passing a contiguous array to a function, is it more preferable to pass a pointer and the size, or a begin-pointer and an end-pointer? [closed]

提问人:JensB 提问时间:9/21/2023 最后编辑:JensB 更新时间:9/21/2023 访问量:123

问:


想改进这个问题吗?更新问题,以便可以通过编辑这篇文章来用事实和引文来回答。

2个月前关闭。

在设计一个需要指针形式的连续数组的函数时,是否应该使用

一个。

指针和数组的大小:

void foo(int* arr, size_t size);

或者 B。

开始指针和结束指针:

void foo(int* arrBegin, int* arrEnd);

显然,两种方法中参数的总大小是相同的,但是有没有充分的理由选择其中一种而不是另一种呢?我相信方法 A. 是更常见的方法,但我看到两者都被频繁使用。在某些情况下,人们会更有意义吗,反之亦然?与另一个相比,一个有什么缺点吗?或者这无关紧要,您应该简单地选择一种方法并坚持下去?

C++ 数组指 函数参数

评论

5赞 Eljay 9/21/2023
如果我使用迭代器惯用语(在 C++ 标准库中很流行,从 Stepanov 的 STL 中采用),我会使用 ,但如果我使用数组(并且只有一个数组),我会使用 或 .template <typename ITER> foo(ITER b, ITER e)void foo(int* arr, size_t size)void foo(pair<int*, size_t> view)
0赞 Ted Lyngmo 9/21/2023
我也会选择Eljay的选项C。这样,函数也将能够处理数据不连续的范围(当然,如果函数内部的操作允许的话)。
7赞 Brian61354270 9/21/2023
还有 std::span 需要考虑。
0赞 YSC 9/21/2023
如果可用,则为首选选项,因为它可以由指针 + 大小或 begin+end 组成。或一个范围。或者 .std::spanstd::array
1赞 Thomas Matthews 9/21/2023
恕我直言,使用迭代器比传递数组和大小更灵活。库函数使用迭代器,例如 .stdstd::sort

答:

0赞 Captain Giraffe 9/21/2023 #1

有一个最不令人惊讶的一般规则

如果我写一个像(像@Elijay建议的那样)的函数

template<typename RandomIt>
void f(RandomIt first, RandomIt last)...

我可以肯定,每个人都使用我的函数、连续容器、参数类型等指针很好地理解它。

最重要的是,第一个最后一个是几乎所有标准库算法和容器的穿鞋。非常方便和容易理解。

我的 2 美分。

0赞 H.S. 9/21/2023 #2

首先,不鼓励在 中使用普通的 C 样式数组。但是,如果由于某些特定原因,您仍然想使用它,那么这是您的选择,如果它仅用于数组,那么任何一种方法都可以。C++

我个人更喜欢方法 B,即开始和结束迭代器(使用迭代器而不是裸指针)方法,因为当数据是连续的时,它更本能。

此外,方法 B 与方法 A 相比有一个优势 - 假设将来您需要将普通的 C 样式数组替换为容器,例如代码中的任何地方,方法 B 更灵活,因为您不需要更改调用位置的任何内容。vectorarrayfoo()

例如: 采用第一种方法 - 方法 A、迭代器和大小:

foo()实现:

template <typename Iterator>
void foo1 (Iterator itrB, std::size_t sz) {
    // iterate over elements
    for (std::size_t i = 0; i < sz; ++i) {
        // access element as itrB[i]
        ....
        ....
    }
}

如果使用普通的 C 样式数组进行调用,则会是这样的:foo()

    int arr[] = {1,2,3,4,5};

    foo(std::cbegin(arr), sizeof (arr) / sizeof (*arr));

假设,您需要将普通的 C 样式数组替换为 ,这就是您需要调用的方式:vector

    std::vector<int> arr = {1,2,3,4,5};

    foo(std::cbegin(arr), arr.size());
                          ^^^^^^^^^^^

您需要修改对数组参数的 everywhere 调用。foo()size

容器也是如此。array

现在,采用第二种方法 - 方法 B,开始和结束迭代器:

foo()实现:

template <typename Iterator>
void foo (Iterator itrB, Iterator itrE) {
    // iterate over elements
    for (auto b = itrB; b != itrE; ++b) {
        // access element as *b
        ....
        ....
    }
}

使用普通的 C 样式数组调用,如下所示:foo()

    int arr[] = {1, 2, 3, 4, 5};

    foo (std::cbegin(arr), std::cend(arr));

跟:vector

    std::vector<int> arr = {1, 2, 3, 4, 5};

调用中不需要更改,相同的调用语句将起作用:foo()

    foo (std::cbegin(arr), std::cend(arr));

请注意,和 中引入的 ,如果您正在使用,则分别将它们替换为 和 。std::cbegin()std::cend()C++14C++11std::begin()std::end()