以下代码在GCC中生成RET指令(https://godbolt.org/z/Yz7fE4xK7)
void f( ) {
std::array<int, 0> a;
std::array<int, 1> b;
std::copy_n(a.begin( ), 0, b.begin( ));
}
但是,以下代码从 GCC 13 开始生成 UD2 指令 (https://godbolt.org/z/7f9KMvr76),显然是由于触发了未定义的行为。
void f( ) {
std::array<int, 0> a;
std::array<int, 1> b;
std::copy_n(&a[0], 0, &b[0]);
}
我相信这是一个 GCC 错误,但我想在实际报告之前询问您的意见,因为未定义的行为是一个棘手的话题。
a[0]
是零大小 std::array
的未定义行为。
a[n]
被定义为等同于序列容器的 *(a.begin() + n)
。
零尺寸
std::array
是与其他情况不同的特殊情况。对零大小 std::array
的唯一保证是 begin()
和 end()
产生相同的值。无论如何,即使存在适当的零大小范围,a.begin() + 0
也不能是可解引用的迭代器,因为它最多指向范围的最后一个元素之后的一个,即它是范围的结束迭代器。
取消引用结束迭代器 (
*
) 违反前提条件并导致未定义的行为。