lower_bound()算法/ STL使用前提条件

时间:2018-08-18 09:37:34

标签: c++ linux stl c++17 stl-algorithm

如果为32位Linux系统编译,下面的代码将返回错误结果,并且在给定足够大的向量的情况下,同样的问题也适用于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 

,结果取决于编译器和stdlib。

1 个答案:

答案 0 :(得分:4)

在libstdc ++中,函数lower_bound(...)使用distance(...),它的开头是:

typedef typename iterator_traits<_ForwardIterator>::difference_type  _DistanceType;
_DistanceType __len = std::distance(__first, __last);
...

根据标准(23.2,[container.requirements]):

  

表达式:a.max_size();返回类型:size_type;操作语义:distance(begin(), end())用于可能的最大容器

distance(...)返回difference_type(24.4.4,[iterator.operations]]

template<class InputIterator>
typename iterator_traits<InputIterator>::difference_type
distance(InputIterator first, InputIterator last);

因此,max_size()返回的值应大于使用带符号类型可以表示的值(在当前情况下为int32_t)。但是,max_size()返回4'294'967'295。我想这是libstdc ++中的错误。

在Microsoft STL实现中,max_size()返回2'147'483'647