我应该声明我的异常的副本构造函数吗? [英] Should I declare the copy constructor of my exceptions noexcept?

查看:72
本文介绍了我应该声明我的异常的副本构造函数吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

斯科特·迈耶斯(Scott Meyers)说,在更有效的C ++

In More Effective C++, Scott Meyers says

C ++指定要复制作为异常抛出的对象.

C++ specifies that an object thrown as an exception is copied.

然后我想,如果复制构造函数又抛出一个异常,则会调用 std :: terminate ,因此这是声明我所有异常的复制构造函数的一个很好的理由 noexcept(而且,我猜也不要抛出从堆中分配内存的对象,例如 std :: string ).

I suppose then, that if the copy constructor throws an exception in turn, std::terminate is called, so this is a good reason for declaring all my exceptions' copy constructors noexcept (and also, I guess, to not throw objects which allocate memory from the heap, like std::string).

但是我很惊讶地看到GCC 4.7.1附带的标准库实现没有为 std :: bad_alloc std :: exception .他们不应该为它们定义 noexcept 吗?

Yet I was surprised to see that the standard library implementation shipped with GCC 4.7.1 doesn’t define those copy constructor for std::bad_alloc and std::exception. Shouldn’t they define them noexcept?

推荐答案

第18.8.1节[exception]/p1指定:

Section 18.8.1 [exception]/p1 specifies:

namespace std {
    class exception {
    public:
      exception() noexcept;
      exception(const exception&) noexcept;
      exception& operator=(const exception&) noexcept;
      virtual ~exception();
      virtual const char* what() const noexcept;
  };
}

即std :: exception的副本构造函数和副本分配应为 noexcept ,并且可以通过以下方式进行测试:

I.e. the copy constructor and copy assignment of std::exception shall be noexcept, and this is testable with:

static_assert(std::is_nothrow_copy_constructible<std::exception>::value, "");
static_assert(std::is_nothrow_copy_assignable<std::exception>::value, "");

即如果某个实现没有使这些成员成为例外,那么这在这方面是不符合要求的.

I.e. if an implementation does not make these members noexcept, then it is not conforming in this regard.

类似地,18.6.2.1 [bad.alloc]/p1也指定了noexcept副本:

Similarly, 18.6.2.1 [bad.alloc]/p1 also specifies noexcept copy:

namespace std {
       class bad_alloc : public exception {
       public:
         bad_alloc() noexcept;
         bad_alloc(const bad_alloc&) noexcept;
         bad_alloc& operator=(const bad_alloc&) noexcept;
         virtual const char* what() const noexcept;
  };
}

此外,所有所有的std定义的异常类型都没有excopy复制成员,无论是显式的还是隐式的.对于< stdexcept> 中定义的类型,通常使用对 what()字符串进行引用计数的缓冲区来实现.在[exception]/p2中明确指出了这一点:

Additionally, all of the std-defined exception types have noexcept copy members, either explicitly, or implicitly. For the types defined in <stdexcept> this is usually implemented with a reference-counted buffer for the what() string. This is made clear in [exception]/p2:

从类异常派生的每个标准库类 T 应具有可公开访问的副本构造函数和可公开访问的副本可访问的副本分配运算符,该运算符不会以例外....

Each standard library class T that derives from class exception shall have a publicly accessible copy constructor and a publicly accessible copy assignment operator that do not exit with an exception. ...

也就是说,在质量实现中(这方面不需要英雄就可以创建质量实现),异常类型的复制成员不仅不会抛出异常(自然地,因为它们被标记为 noexcept)),它们也不会调用 terminate().

That is, in a quality implementation (and it does not take heroics to create a quality implementation in this regard), not only will the copy members of exception types not throw an exception (naturally because they are marked noexcept), they also will not call terminate().

没有用于复制std定义的异常类型的故障模式.没有要复制的数据,或者数据是按引用计数且不可变的.

There is no failure mode for copying the std-defined exception types. Either there is no data to copy, or the data is reference counted and immutable.

这篇关于我应该声明我的异常的副本构造函数吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆