问题描述
我今天早些时候参加了在线编程竞赛。有一个问题,我必须处理三个输入向量,其中一个需要排序。在一个简单的示例中,我的代码如下:
vector <int> a;
vector <int> b;
.
.
.
sort(begin(a),end(b));
请注意,我是如何错误地(/愚蠢地)输入错字sort(begin(a),end(b)
。我花了相当长的时间才能弄清这个错误,因为运行时错误消息没有说明任何错误。
c:\programming\mingw\mingw 9.2.0\include\c++\9.2.0\bits\stl_algo.h:4825:
In function:
void std::sort(_RAIter,_RAIter) [with _RAIter =
__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<int*,std::__cxx1998::vector<int,std::allocator<int> > >,std::__debug::vector<int>,std::random_access_iterator_tag>]
Error: function requires a valid iterator range [__first,__last).
Objects involved in the operation:
iterator "__first" @ 0x000000000023fdb0 {
type = __gnu_cxx::__normal_iterator<int*,std::allocator<int> > >
(mutable iterator);
state = dereferenceable (start-of-sequence);
references sequence with type 'std::__debug::vector<int,std::allocator<int> >' @ 0x0000000000
23FD10
}
iterator "__last" @ 0x000000000023FD80 {
type = __gnu_cxx::__normal_iterator<int*,std::allocator<int> > >
(mutable iterator);
state = past-the-end;
references sequence with type 'std::__debug::vector<int,std::allocator<int> >' @ 0x0000000000
23FCD0
}
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
我唯一想看的部分是Error: function requires a valid iterator range [__first,__last).
。我花了大约10分钟的时间漫不经心地思考着我在做错什么,尽管我几次浏览了一下分类部分,却没有注意到自己的愚蠢错误。我什至不知道这是有可能的(即使我已经看过很多次函数定义了!)!
所以,我的问题是:为什么C ++算法允许这样做,为什么C ++委员会没有为此做些什么?为什么编译器不喊?是否故意采用这种方式来惩罚人们像C ++中的所有其他事物一样使用C ++犯傻错误?
解决方法
为什么C ++算法允许这样做,为什么C ++委员会没有为此做些什么?
因为这不是可以解决的问题。假设您有一个int arr[500];
之类的数组,并且希望对其进行排序。您将传递arr
和arr + 500
作为要排序的参数,但它们只是int*
的参数。他们没有其他信息,而是他们指向的地址。 sort
无法检查这两个指针是否指向相同的内存块。
对于标准容器的迭代器而言,这是相同的。迭代器无法提供访问其来源容器的方法,因此sort
无法检查迭代器是否指向同一对象。
为什么?因为否则,您将付出检查在编译时应检查的内容的运行时成本:迭代器需要使用它们来自的容器进行注释,而sort
则需要进行检查。
换句话说:您的有效投诉不应针对C ++库,而应针对不包含对此静态检查的编译器。静态代码分析器(例如PVS-Studio)通常会捕获此问题。静态代码分析器将捕获更多新秀错误,这些错误可能会导致浪费大量时间,因此建议您为自己配备一个。由于我最熟悉PVS-Studio,因此我可以立即告诉您它是free for student use。