lower_bound() algorithm/STL 使用前提条件
lower_bound() algorithm/STL usage preconditions
如果为 32 位 Linux 系统编译,下面的代码 returns 会产生错误结果,同样的问题也适用于 64 位系统,给定足够大的向量。
是否违反了 lower_bound 或 STL 的一般先决条件,如果违反了,在哪里?
我从 STL 消息来源获悉,向量的大小被强制转换为有符号类型,这解释了这种行为。
// compile with and without -m32 switch
#include<algorithm>
#include<iostream>
#include<stdexcept>
#include<vector>
using namespace std;
int main() {
try {
vector<uint8_t> v((1ULL << 28) * 9, 2); // 2.25 G entries
v.back() = 3; // the last of which is greater
cout<< "Vector maximal size: "<<v.max_size()<< " and actual size: " << v.size() <<endl;
uint8_t val=3;
auto x= lower_bound(v.begin(), v.end(), val );
if (x!=v.end() && !( val< *x ) ) {
cout << "Found value " << int(*x) << endl;
} else {
cout << "Not Found " << endl;
}
} catch (exception const & ex){
cerr<< ex.what()<<endl;
}
}
输出:(Linux OS & Clang++ 7.0.0)
Vector maximal size: 4294967295 and actual size: 2415919104
Found value 2
输出:(Windows 10 OS & 32bit-msvc)
vector<T> too long
更新:虽然正在修复 std::vector,但问题仍然存在于由
分配的数组
auto p= new uint8_t[sz]; // 2.25 G entries
结果取决于编译器和标准库。
在 libstdc++ 中,函数 lower_bound(...)
使用 distance(...)
,它以:
开头
typedef typename iterator_traits<_ForwardIterator>::difference_type _DistanceType;
_DistanceType __len = std::distance(__first, __last);
...
根据标准 (23.2, [container.requirements]):
Expression: a.max_size()
; return type: size_type
; operational semantics: distance(begin(), end())
for the largest possible container
distance(...)
returns difference_type
(24.4.4, [iterator.operations]]
template<class InputIterator>
typename iterator_traits<InputIterator>::difference_type
distance(InputIterator first, InputIterator last);
因此,max_size()
应该 return 一个可以使用带符号类型表示的值(在本例中为 int32_t
)。然而,max_size()
returns 4'294'967'295
。我想这是 libstdc++ 中的一个错误。
顺便说一下,在 Microsoft STL 实现中 max_size()
returns 2'147'483'647
.
如果为 32 位 Linux 系统编译,下面的代码 returns 会产生错误结果,同样的问题也适用于 64 位系统,给定足够大的向量。
是否违反了 lower_bound 或 STL 的一般先决条件,如果违反了,在哪里?
我从 STL 消息来源获悉,向量的大小被强制转换为有符号类型,这解释了这种行为。
// compile with and without -m32 switch
#include<algorithm>
#include<iostream>
#include<stdexcept>
#include<vector>
using namespace std;
int main() {
try {
vector<uint8_t> v((1ULL << 28) * 9, 2); // 2.25 G entries
v.back() = 3; // the last of which is greater
cout<< "Vector maximal size: "<<v.max_size()<< " and actual size: " << v.size() <<endl;
uint8_t val=3;
auto x= lower_bound(v.begin(), v.end(), val );
if (x!=v.end() && !( val< *x ) ) {
cout << "Found value " << int(*x) << endl;
} else {
cout << "Not Found " << endl;
}
} catch (exception const & ex){
cerr<< ex.what()<<endl;
}
}
输出:(Linux OS & Clang++ 7.0.0)
Vector maximal size: 4294967295 and actual size: 2415919104 Found value 2
输出:(Windows 10 OS & 32bit-msvc)
vector<T> too long
更新:虽然正在修复 std::vector,但问题仍然存在于由
分配的数组auto p= new uint8_t[sz]; // 2.25 G entries
结果取决于编译器和标准库。
在 libstdc++ 中,函数 lower_bound(...)
使用 distance(...)
,它以:
typedef typename iterator_traits<_ForwardIterator>::difference_type _DistanceType;
_DistanceType __len = std::distance(__first, __last);
...
根据标准 (23.2, [container.requirements]):
Expression:
a.max_size()
; return type:size_type
; operational semantics:distance(begin(), end())
for the largest possible container
distance(...)
returns difference_type
(24.4.4, [iterator.operations]]
template<class InputIterator> typename iterator_traits<InputIterator>::difference_type distance(InputIterator first, InputIterator last);
因此,max_size()
应该 return 一个可以使用带符号类型表示的值(在本例中为 int32_t
)。然而,max_size()
returns 4'294'967'295
。我想这是 libstdc++ 中的一个错误。
顺便说一下,在 Microsoft STL 实现中 max_size()
returns 2'147'483'647
.