std::begin 是空的 std::valarray 未定义行为吗?
Is std::begin on an empty std::valarray undefined behavior?
我在玩 std::valarray
和 UndefinedBehaviorSanitizer,并注意到 std::begin
一个空的 std::valarray
会导致未定义的行为。这是代码:
#include <valarray>
int main() {
std::valarray<int> a;
std::begin(a);
}
要重现,请使用 g++ -fsanitize=undefined
编译代码并 运行 结果可执行文件。
这是 libstdc++ 的 std::begin
实现。
template<class _Tp>
inline _Tp*
begin(valarray<_Tp>& __va)
{ return std::__addressof(__va[0]); }
似乎 _val[0]
为空 std::valarray
创建了一个空值引用,这导致了未定义的行为。
这是 libstdc++ 的错误吗?
n4659 - C++17 final working draft
§26.2.1 General container requirements
[container.requirements.general]
Table 83 — Container requirements
a.begin()
- no precondition
所以 a.begin()
必须在空容器上有效。
但是 valarray
是在 §29.7 数值数组 [numarray] 中定义的 §29 数值库 [numerics]章节,所以它不是容器库章节的直接部分。
std::begin(valarray)
在§29.7.10 valarray range access [valarray.range]中定义,这里没有提到前提条件。最相关的名言是:
§ 29.7.10 valarray range access [valarray.range]
The iterators returned by begin
and end
for an array are
guaranteed to be valid until the member function resize(size_t, T)
(29.7.2.8) is called for that array or until the lifetime of that
array ends, whichever happens first.
template <class T> unspecified 1 begin(valarray<T>& v);
template <class T> unspecified 2 begin(const valarray<T>& v);
Returns: An iterator referencing the first value in the array.
所以问题是 Table 83 是否适用于此。 valarray
在 §29.7.2 Class template valarray [template.valarray] 中描述并且标准说:
29.7.2.1 Class template valarray overview [template.valarray.overview]
- The class template valarray is a one-dimensional smart array,
在我看来这意味着 valarray
是属于 §26.2.1 一般容器要求
的容器
对我来说,空 valarray
上的 std::begin
应该是有效的。另一方面,“Returns:引用数组中第一个值的迭代器”可能暗示一个先决条件,即 valarray
不能为空。所以我唯一的结论是,标准在这方面应该更加明确。
我在玩 std::valarray
和 UndefinedBehaviorSanitizer,并注意到 std::begin
一个空的 std::valarray
会导致未定义的行为。这是代码:
#include <valarray>
int main() {
std::valarray<int> a;
std::begin(a);
}
要重现,请使用 g++ -fsanitize=undefined
编译代码并 运行 结果可执行文件。
这是 libstdc++ 的 std::begin
实现。
template<class _Tp>
inline _Tp*
begin(valarray<_Tp>& __va)
{ return std::__addressof(__va[0]); }
似乎 _val[0]
为空 std::valarray
创建了一个空值引用,这导致了未定义的行为。
这是 libstdc++ 的错误吗?
n4659 - C++17 final working draft
§26.2.1 General container requirements [container.requirements.general]
Table 83 — Container requirements
a.begin()
- no precondition
所以 a.begin()
必须在空容器上有效。
但是 valarray
是在 §29.7 数值数组 [numarray] 中定义的 §29 数值库 [numerics]章节,所以它不是容器库章节的直接部分。
std::begin(valarray)
在§29.7.10 valarray range access [valarray.range]中定义,这里没有提到前提条件。最相关的名言是:
§ 29.7.10 valarray range access [valarray.range]
The iterators returned by
begin
andend
for an array are guaranteed to be valid until the member functionresize(size_t, T)
(29.7.2.8) is called for that array or until the lifetime of that array ends, whichever happens first.template <class T> unspecified 1 begin(valarray<T>& v); template <class T> unspecified 2 begin(const valarray<T>& v);
Returns: An iterator referencing the first value in the array.
所以问题是 Table 83 是否适用于此。 valarray
在 §29.7.2 Class template valarray [template.valarray] 中描述并且标准说:
29.7.2.1 Class template valarray overview [template.valarray.overview]
- The class template valarray is a one-dimensional smart array,
在我看来这意味着 valarray
是属于 §26.2.1 一般容器要求
对我来说,空 valarray
上的 std::begin
应该是有效的。另一方面,“Returns:引用数组中第一个值的迭代器”可能暗示一个先决条件,即 valarray
不能为空。所以我唯一的结论是,标准在这方面应该更加明确。