【问题标题】:C++ checking uninitialized iteratorsC++ 检查未初始化的迭代器
【发布时间】:2013-10-31 14:27:12
【问题描述】:

我浪费了大量时间,因为我忘记初始化迭代器然后尝试访问它们应该指向的数据。出现此类错误的唯一标记是运行时的分段错误。这是一个例子:

vector<Foo> V;
//Uninitialized pointer:
vector<Foo>::iterator it;
//....loads of code later, attempt to access pointer that points to nothing
(*it);
//Segmentation fault!

是否有一种标准技术可以在编译时自动进行这种检查?

【问题讨论】:

  • 实用解决方案:将迭代器定义移到 "... loading of code" 位之后。
  • 使用惯用代码? for (auto it = v.begin(); ...)
  • 如何将“代码量”减少到“一点点代码”?
  • 尽可能晚地声明迭代器,并在声明时对其进行初始化。
  • 我很乐意,但迭代器包含在包装器中。我正在尝试将实现 vector&lt;Foo&gt; 从通用算法中抽象出来,因此我使用包装器的成员函数来控制迭代器。

标签: c++ iterator initialization segmentation-fault


【解决方案1】:

在编译时?没有。

我能想到几个运行时助手。首先是使用boost::optional。第二种是设置一个可以用来初始化迭代器的哨兵向量。

static vector<Foo> null_vector;
vector<Foo>::iterator it = null_vector.begin();
...
if (it == null_vector.begin())

【讨论】:

  • 哨兵是一种严重的代码气味,但这个更好。想一想,在很多情况下,optional 就是这样。我不能说我不同意你的回答,事实上我同意optional,所以+1。
  • @JohnDibling,有些人出于某种原因厌恶boost,所以我提供了一个替代方案。
  • 当然,有道理。我也不能将 Boost 用于生产代码。为此,我开发了自己的optional
【解决方案2】:

在 C++14 中,compare value initialized iterators 可以接受。 (2013 年 4 月通过)

所以这是真的:

vector<int>::iterator i1{};
vector<int>::iterator i2{};
assert(i1 == i2);

但这仍然无效:

vector<int>::iterator i1;
vector<int>::iterator i2;
assert(i1 == i2);

不过,我不确定哪些编译器支持此功能。

【讨论】:

    【解决方案3】:

    我在实际代码中使用了一些技术。没有一个是您正在寻找的。​​p>

    首先,作为一种编程习惯,我通常在靠近需要它的地方实例化一个变量,并且在我可以初始化它的时候。我从不实例化未初始化的变量。

    有时不可能在一个地方实例化和初始化。在这些情况下,我将使用类似 Boost 的 optional 之类的东西,并在需要使用它的时候检查是否设置了 optional

    我经常发现,当无法在一个地方实例化和初始化时,是因为某些函数的设计笨拙笨拙,或者它试图做的太多。尝试将这些职责分解为多个函数,您可能会发现最初的问题 - 无法在一个地方初始化和实例化 - 消失了,并且产生了更清晰的代码。

    【讨论】:

      猜你喜欢
      • 2012-02-09
      • 2011-10-20
      • 2011-07-13
      • 2012-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-03
      相关资源
      最近更新 更多