Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么';tc++;字符串迭代器检查错误?_C++_Error Handling_Stl_Iterator - Fatal编程技术网

C++ 为什么';tc++;字符串迭代器检查错误?

C++ 为什么';tc++;字符串迭代器检查错误?,c++,error-handling,stl,iterator,C++,Error Handling,Stl,Iterator,我是一名大学生。我的任务是写单链表。我开始用nodes exposed()实现它,但使用时会导致许多空检查。然后我将节点设为私有,列表元素通过迭代器()公开,因此没有空检查,但仍然需要检查迭代器是否不在列表的末尾。我想写一个很好的实现,所以我做了一个简单的测试来检查C++ STL如何处理一些错误: #include <iostream> using namespace std; int main() { string first = "afasdasds"; string

我是一名大学生。我的任务是写单链表。我开始用nodes exposed()实现它,但使用时会导致许多空检查。然后我将节点设为私有,列表元素通过迭代器()公开,因此没有空检查,但仍然需要检查迭代器是否不在列表的末尾。我想写一个很好的实现,所以我做了一个简单的测试来检查C++ STL如何处理一些错误:

#include <iostream>

using namespace std;

int main()
{
  string first = "afasdasds";
  string second = "asdadas";
  int i = 0;
  for(auto it = first.begin(); i < 100; it++)
  {
    bool result = it > second.begin();
    cout << result;
    i++;
  }
}
#包括
使用名称空间std;
int main()
{
string first=“afasdasds”;
字符串second=“asdadas”;
int i=0;
for(auto it=first.begin();i<100;it++)
{
bool result=it>second.begin();

这是一种权衡,性能与安全

检查会减慢速度。对于迭代器来说,由于它们在紧循环中递增和取消引用,因此可能相当于一个

STL
的许多实现通过使用库的调试版本和发布版本来缓解这一问题,因此您可以在测试期间使用检查运行,但在发布时不使用检查

不管
STL
的基本原理是什么,它都鼓励更安全的编程。如果你想一想,迭代器应该总是来自一个安全的地方

也就是说,在流程开始时,您可以通过调用容器的
begin()
end()
函数获取迭代器,或者作为算法返回的结果,例如
std::find

此外,还可以使用更安全的构造,例如

这种编程风格有助于保持边界安全。

当您使用索引或迭代器偏移量时,真正危险的事情就会发生,如果可能的话,应该避免这种情况。此外,存储迭代器供以后使用也不是很安全

所以一定要使用迭代器,不要使用索引(除非必须)。尽量避免让迭代器无法立即使用

但是,最重要的是,使用
DEBUG
版本和test,test,test,这样您的边界检查就可以非常可靠地完成

迭代器不应该检查比较是否有意义吗

++操作符不应该检查它是否已溢出吗

因此,如果我正确地编写代码——我的意思是静态地、可证明地正确,这样在逻辑上就不会出错——我还需要为您添加的所有代码支付运行时成本来检测错误吗

您的代码应该是正确的。如果您的实现执行了这些检查,并且它们检测到错误,这意味着您的代码首先是错误的。拥有帮助您检测和修复错误的工具非常有用,但它们应该是调试辅助工具,而不是拐杖

…显然,比较不同列表中的迭代器会产生错误

比较不同列表中的迭代器会产生一个错误:在代码审查期间


此外,如果避免支付这些检查的运行时成本的唯一方法是避免使用标准库,那么许多人实际上将不得不避免使用标准库,而拥有一个人们实际上并不使用的标准库的好处有限。

如果您的目标是调试和测试,那么对于gcc,您可以使用我们可以作为GNU扩展提供

第一个示例可以使用
\uu gnu\u debug::string
而不是
std::string
重写:

#include <iostream>
#include <debug/string>

using namespace std;

int main()
{
  __gnu_debug::string first = "afasdasds";
  __gnu_debug::string second = "asdadas";
  int i = 0;
  for(auto it = first.begin(); i < 100; it++)
  {
    bool result = it > second.begin();
    cout << result;
    i++;
  }
}
#包括
#包括
使用名称空间std;
int main()
{
__gnu_debug::string first=“afasdasds”;
__gnu_调试::string second=“asdadas”;
int i=0;
for(auto it=first.begin();i<100;it++)
{
bool result=it>second.begin();

CUT不,不应该——C++的设计哲学的一部分是你不为你不明确要求的东西付费。所以检查一个迭代器是否仍然在范围内是程序员的任务,没有这样的要求。程序员不应该越界。使用迭代器的<代码> > <代码>的正确方法是<代码> f。或者(auto-it=first.begin();it!=first.end();++it)
-在我看来很简单,应该是
for(const-auto&c:first)
@UnholySheep,甚至
for(auto&char:first) >然后是在引擎盖下完成的:“可以说,使用迭代器的调试版本和测试、测试、测试,使用的是C++的更多范例。在这种情况下:基于循环的范围。”我想我的答案也涵盖了这一点,但我可以在这上面加一些。涉及到这个问题。它只是说明了不应该做什么。巧合的是,基于范围的for循环甚至不允许你做大部分(所有?)这些事情。但是你从来没有明确地命名过这个构造。
test test*text*
?需要更多的测试;@UKMonkey Thnx(我应该假装我这样做是为了说明这一点……)这个调试输出特别有用,因为它还显示了OP甚至没有询问的东西,即完全不相关的“容器”的迭代器之间的无效比较。
#include <iostream>
#include <debug/string>

using namespace std;

int main()
{
  __gnu_debug::string first = "afasdasds";
  __gnu_debug::string second = "asdadas";
  int i = 0;
  for(auto it = first.begin(); i < 100; it++)
  {
    bool result = it > second.begin();
    cout << result;
    i++;
  }
}
$ ./a.out 
/usr/include/c++/7/debug/safe_iterator.h:658:
Error: attempt to order iterators from different sequences.

Objects involved in the operation:
    iterator "lhs" @ 0x0x7ffd4285a5e0 {
      type = __gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_debug::basic_string<char, std::char_traits<char>, std::allocator<char> > > (mutable iterator);
      state = dereferenceable (start-of-sequence);
      references sequence with type '__gnu_debug::basic_string<char, std::char_traits<char>, std::allocator<char> >' @ 0x0x7ffd4285a650
    }
    iterator "rhs" @ 0x0x7ffd4285a690 {
      type = __gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_debug::basic_string<char, std::char_traits<char>, std::allocator<char> > > (mutable iterator);
      state = dereferenceable (start-of-sequence);
      references sequence with type '__gnu_debug::basic_string<char, std::char_traits<char>, std::allocator<char> >' @ 0x0x7ffd4285a610
    }
Aborted (core dumped)