什么是半开区间和超出值?

28

这些术语在C++中是什么意思?

1. off the end value (超出结尾值)

2. half open range - [begin, off_the_end) (半开区间 - [起始值, 超出结尾值))

我在读有关for循环的资料时遇到了它们。


1
不包括边缘值。它主要用于处理实数/有理数,但也可以应用于整数。 - amit
3个回答

41

半开区间是包括第一个元素但不包括最后一个元素的区间。

[1,5) 是一个半开区间,包含了值为1、2、3和4的元素。

"超过结尾"或者"越过结尾"指的是序列末尾的元素之后的位置,并且这个位置很特殊,因为迭代器可以指向它(但你不能查看实际值,因为它不存在)。

例如,在以下代码中:

char arr[] = {'a', 'b', 'c', 'd'};

char* first = arr
char* last = arr + 4;

first 现在指向数组的第一个元素,而 last 指向数组的结尾处之后的一个位置。我们可以指向数组结尾之后的一个位置(但不是两个位置),但是我们不允许尝试访问该位置的元素:

// legal, because first points to a member of the array
char firstChar = *first;
// illegal because last points *past* the end of the array
char lastChar = *last;

我们的两个指针firstlast 共同定义了一个范围,即它们之间的所有元素。

如果这是一个半开区间,则包含被first指向的元素和它们之间的所有元素,但不包括被last指向的元素(这很好,因为它实际上并不指向有效的元素)。

在 C++ 中,所有标准库算法都操作此类半开区间。例如,如果我想将整个数组复制到某个其他位置 dest,我会这样做:

std::copy(first, last, dest)

一个简单的for循环通常遵循相似的模式:

for (int i = 0; i < 4; ++i) {
    // do something with arr[i]
}

这个循环从0到4,但不包括结束值,所以索引范围是半开放的,具体地说是[0, 4)


28

这些术语不是特定于 C++ 的术语,而是普遍的数学术语。

[] 和 () 表示范围是否包含端点:

  • [ 包含端点
  • ( 排除端点
  • [] = “闭区间”,包括两个端点
  • () = “开区间”,排除两个端点
  • [) 和 (] 都是“半开区间”,只包括一个端点

大多数 C++ for 循环包含一个半开区间(您包括第一个元素:例如 for int i=0;,但排除最后一个元素:i < foo,而不是 i ≤ foo


更具体地说,你所描述的数学符号有一个名称:区间表示法。 - Michael M.

1
正如其他答案所解释的那样,“半开区间”也是一个数学术语,而在编程上下文中使用这个术语时,它暗示了起始点是“包括”的,而结束点是“不包括”的。
在C/C++编程中,它实际上意味着什么?假设你要打印一个整数数组的元素。就C语言而言,因为你对数组大小没有任何运行时知识,你有两个选择。要么你必须提供数组的大小,因此函数签名将如下所示;
void printArray(int * array, int size);

或者你必须使用半开区间,这意味着你必须提供开始和结束指针(函数将处理包括开始但不包括结束),除了数组本身。而函数签名将如下所示;

void printArray(int * array, int * begin, int * end);

为了举例说明,这里提供一个关于提供数组大小的示例;
#include <stdio.h>

void printArray(int * array, int size)
{
    printf("Array: ");

    for(int i = 0; i < size; i++)
        printf("%2d ", array[i]);

    printf("\n");
}

int main()
{
    int array[5] = { 1, 2, 3, 4, 5 };

    printArray(array, 5);

    return 0;
}

在上面的例子中,我们向printArray函数传递了两个参数,正如函数签名所示,第一个数组元素(或数组本身)的指针和数组的大小。
然而,正如我之前所写的,我们也可以在函数签名中使用半开区间,如下所示:
#include <stdio.h>

void printArray(int * array, int * begin, int * end)
{
    printf("Array: ");

    for(int * index = begin; index != end; index++)
        printf("%2d ", *index);

    printf("\n");
}

int main()
{
    int array[5] = { 1, 2, 3, 4, 5 };

    printArray(array, array, array+5);

    return 0;
}

这两段代码将产生相同的输出,如下所示:

Array:  1  2  3  4  5

如你所见,printArray 函数打印了 [begin, end) 范围内的函数。实际上,index 是指向整数数组元素的指针,从 begin 开始,并且包括 begin,当 index 等于 end 指针时,结束 for 循环,不处理 end。这被称为半开区间

半开区间C++惯例


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接