【问题标题】:move constructor for std::runtime_error移动 std::runtime_error 的构造函数
【发布时间】:2015-03-16 19:24:04
【问题描述】:

为什么std::runtime_error 不提供接受std::string&& 的构造函数?查看the constructors for std::string,它有一个移动构造函数,但noexcept 规范仅适用于C++14,不适用于C++11。这是一个错误,错过了最后期限还是我错过了什么?

【问题讨论】:

  • 如果std::runtime_error 有一个构造函数采用std::string&&,它肯定不会是一个移动构造函数。移动构造函数将采用 std::runtime_error&&
  • 我不确定我是否遵循:从一开始就判断您的问题似乎是关于runtime_error,但随后您切换到std::string。你想表达什么观点?
  • @AndyProwl: std::runtime_error 目前可能由const std::string&const char* what_arg 构建。他在问为什么它不能从 std::string&& 构建。
  • @LightnessRacesinOrbit:是的,但他似乎通过提到string 的移动构造函数的noexcept 资格来说明异常安全性,我并不完全遵循。
  • 是的,如果问题引起了混乱,我很抱歉。问题是为什么std::runtime_error(std::string&&) 不存在。

标签: string exception c++11 move c++14


【解决方案1】:

explicit runtime_error(string&&);

不存在仅仅因为它不会提供任何优化。

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

这意味着runtime_error 需要存储一个不可变的引用计数字符串。但是 C++11 禁止 std::string 的 COW 实现。 std::string 的实现已移至“短字符串优化”,如果字符串的长度超出“短限制”,则必须在复制构造时进行分配。而且用于构造runtime_error的字符串长度没有限制。

因此,C++11(和之前)实际上包含两个字符串实现:

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

  2. std::runtime_error :这是(或持有)一个不可变的引用计数字符串。这绝不会引发复制构造或复制分配。

explicit runtime_error(string&&);

永远不能(有效地)将资源从“type 1”字符串转移到“type 2”字符串。

【讨论】:

  • 类型 2 字符串会是什么样子,出于兴趣? (如果它是一个黑盒、隐藏、实现定义的内部类型,那么这就足够了。)
  • 它可能看起来像基于 C++03 COW 的 std::string 的非变异部分。事实上,这正是 libc++ 所做的。它的类型 2 字符串具有与 gcc-4.2 std::string 相同的 ABI,因此runtime_error 可以从 libc++ 中抛出并使用 libstdc++ 捕获(反之亦然),在同一应用程序中
  • 你为什么要这样做?
  • 当 libc++ 和 libstdc++ 是 dylib 时,当一个应用程序由许多 dylib 组成时,在 OS X 等平台上的过渡期间,应用程序很可能会在不知不觉中间接链接对于 libc++ 和 libstdc++,除非该应用程序可以直接控制它使用的所有 dylib 的构建。
  • 同样,GCC5 中的 libstdc++ 在其异常类型中仍然使用旧的 COW std::string(通过不透明类型和一些可怕的骇客),即使新的 SSO std::string 对用户可见.这应该支持使用来自 GCC4、GCC5 或 libc++ 的任何 std::string 在代码中抛出 std::runtime_error,并使用不同的 std::string 在代码中捕获它。
猜你喜欢
  • 2014-07-16
  • 2021-01-01
  • 2011-11-25
  • 1970-01-01
  • 2014-05-02
  • 2018-03-12
  • 2015-04-26
  • 2016-05-04
相关资源
最近更新 更多