【问题标题】:Can vector<T>::clear throw?vector<T>::clear 可以抛出吗?
【发布时间】:2011-11-09 13:50:44
【问题描述】:

调用std::vector&lt;T&gt;::clear() 是否有机会引发异常?

【问题讨论】:

  • 很好的问题,暴露了很多人不知道正确答案!
  • @VJo:在您删除答案之前,我没有机会回复。 “这使得只能从一个对象抛出异常”:怎么会?

标签: c++ exception vector


【解决方案1】:

没有。

[2003: 21.2.1/11 | n3290: 21.2.1/10]: 除非另有说明 (见 23.2.4.1、23.2.5.1、23.3.3.4 和 23.3.6.5)所有容器类型 本条款中定义的满足以下附加要求: [..] — 没有erase()clear()pop_back()pop_front() 函数抛出异常。 [..]


如果我的元素类型析构函数抛出,会发生什么?

在 C++11 中,std::vector&lt;T&gt;::clear() 标记为 noexcept ([n3290: 23.3.6/1])。

任何脱离~T 的异常都可以被实现捕获,因此clear() 本身可能不会抛出任何东西。如果它们不是,并且确实如此,则异常是“意外的”并终止进程而不是传播:

struct T {
   ~T() { throw "lol"; }
};

int main() {
   try {
      vector<T> v{T()};
      v.clear();
   }
   catch (...) {
      cout << "caught";
   }
}

// Output: "terminated by exception: lol" (GCC 4.7.0 20111108)

[n3290: 15.5.1]:在某些情况下必须进行异常处理 放弃了不太微妙的错误处理技术。 [..] - 当。。。的时候 搜索处理程序 (15.3) 遇到 a 的最外层块 no-except-specification 的函数不允许 例外 (15.4) [..]

【讨论】:

  • 我认为实例化 vector 的元素类型的要求之一是它的析构函数不会抛出。如果您违反要求,则行为未定义,因此实现无需捕获来自~T() 的异常。
  • @James:很公平。我猜.clearnoexcept 以添加额外的诊断安全层。
  • @James:我刚刚重新审视了您的评论并最终正确理解了它。我的“必须抓住”放错了地方,并不是那个意思。 :)
【解决方案2】:

是的,如果T的析构函数抛出,否则不会。

更新: 看来我错了;在那种情况下它只会崩溃

【讨论】:

  • 所以我想说,只要我使用 std:: 类型就不会抛出(因为它们不会抛出 dtors),对吗?
【解决方案3】:

是与否

是的:

clear 最终调用delete[] 运算符,这涉及调用数组(如果有的话)和free 内存中所有对象的析构函数。

析构函数最终可能会抛出异常。

在异常情况下(例如堆损坏等),内存释放也可能失败

没有:

抛出异常是析构函数受到批评并且大多数情况下不会发生(至少在标准库中)。除了在堆栈展开期间析构函数抛出的异常(由另一个异常引起)可能无法处理之外,析构函数中的异常存在逻辑问题。

释放内存的错误通常是由堆损坏或其他不可恢复的问题引起的。反正程序的命运就是死,不管有没有例外

【讨论】:

  • 这是不正确的。 clear(实际上没有std::vector的函数)永远不会调用delete[]
  • @James Kanze:是的,你是对的,向量不会这么快释放内存
猜你喜欢
  • 2017-10-06
  • 2016-11-26
  • 1970-01-01
  • 1970-01-01
  • 2017-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多