移动std :: runtime_error的构造函数

rwo*_*ols 9 string exception move c++11 c++14

为什么不std::runtime_error提供构造函数接受std::string&&?看一下构造函数std::string,它有一个移动构造函数,但noexcept规范仅适用于C++ 14,而不是C++ 11.这是一个错误,错过了截止日期还是我错过了什么?

How*_*ant 14

explicit runtime_error(string&&);

不存在只是因为它不会提供任何优化.

事实证明,符合C++ 11标准的runtime_error内部不存储std::string.原因是复制成员runtime_error不得抛出异常.否则,当编译器在抛出异常对象的过程中复制异常对象时,可能会抛出错误的异常.

这意味着runtime_error需要存储一个非可变引用计数字符串.但是,C++ 11取消了COW实现std::string.的实现std::string已经转移到"短串优化",这必须在拷贝构造分配如果字符串的长度超出了"短极限".并且用于构造a的字符串的长度没有限制runtime_error.

所以有效的C++ 11(和转发)包含两个字符串实现:

  1. std::string :这通常是一个短字符串优化类型,具有复制构造函数和能够抛出异常的复制赋值.

  2. std::runtime_error:这是(或保持)不可变引用计数字符串.这绝不会引发复制构建或复制分配.

和

explicit runtime_error(string&&);

永远不能(有效地)将资源从"类型1"字符串传输到"类型2"字符串.

  • 它看起来像是基于C++ 03 COW的`std :: string`的非变异部分.实际上,这正是libc ++所做的.它的类型2字符串有一个与gcc-4.2`std :: string`相同的ABI,因此`runtime_error`可以从libc ++中抛出并使用libstdc ++(反之亦然)*在同一个应用程序*中捕获. (5认同)
  • 当libc ++和libstdc ++是dylib时,并且当应用程序由许多dylib组成时,很可能在OS X等平台上的过渡期间,应用程序将无意中,间接地链接到libc ++和libstdc ++,除非说应用程序可以直接控制它使用的所有dylib的构建. (5认同)
  • 类似地,GCC5中的libstdc ++仍然在其异常类型中使用旧的COW`std :: string`(通过opaque类型和一些可怕的hackery),即使新的SSO`std :: string`是用户可见的.这应该支持使用来自GCC4,GCC5或libc ++的任何`std :: string`在代码中抛出`std :: runtime_error`,并使用不同的`std :: string`在代码中捕获它. (4认同)