You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

什么决定std::runtime_error子类是否为is_nothrow_copy_constructible?

Why does my custom std::runtime_error subclass's is_nothrow_copy_constructible status vary across environments?

Let's break down exactly what's going on here—your custom exception's noexcept copy constructibility boils down to subtle standard library implementation details and environment-specific compile configurations, even when compiler and library versions look identical.

Key Factors Determining is_nothrow_copy_constructible

1. libstdc++'s implementation of std::exception

At the root of this is how std::exception (the base class of std::runtime_error) is implemented:

  • The C11+ standard allows, but does not require, std::exception's copy constructor to be noexcept. This gives libstdc maintainers flexibility in how they implement it.
  • Starting with GCC 5.x, libstdc++ defaults to marking std::exception's copy constructor as noexcept. Since your custom_error inherits from std::runtime_error (which inherits from std::exception), your class automatically gets this noexcept attribute for its implicit copy constructor (assuming you don't explicitly override it to be non-noexcept).
  • GCC 4.x's libstdc++ doesn't include this noexcept marker on std::exception, so your subclass won't have it either.

2. Standard library compilation flags

Even with the same libstdc++ version (like your 6.0.25), compile-time configuration can change std::exception's behavior:

  • Distributions sometimes compile libstdc++ with debug flags like _GLIBCXX_DEBUG. In debug mode, libstdc++ often removes noexcept markers from std::exception's copy constructor because debug checks might throw exceptions (which would violate noexcept).
  • Your Travis-CI Ubuntu 14.04 environment is likely using a libstdc++ build with these debug flags enabled, whereas your local Ubuntu 18.04 setup uses the default non-debug build—hence the discrepancy even with matching version numbers.

3. Implicit copy constructor rules

When you don't define a copy constructor for custom_error, the compiler generates one implicitly. The noexcept status of this implicit constructor depends entirely on the noexcept status of all base class and member variable copy constructors:

  • If std::runtime_error's copy constructor is noexcept (and all your custom members also have noexcept copy constructors), your implicit copy constructor will be noexcept.
  • If any base or member's copy constructor isn't noexcept, your implicit constructor won't be either.

Breaking Down Your Specific Scenarios

  • Compiler Explorer GCC 5.x+ vs 4.x: GCC 5.x+ uses the newer libstdc++ with std::exception's noexcept copy constructor, so your custom_error is is_nothrow_copy_constructible. GCC 4.x uses the older implementation without the marker, so it's not.
  • Local Ubuntu 18.04: Your system's libstdc++.so.6.0.25 is compiled in non-debug mode, so std::exception's copy constructor is noexcept. Both GCC and Clang link against this library, so your class inherits the noexcept property regardless of compiler.
  • Travis-CI Ubuntu 14.04: Even with matching compiler and library versions, the environment's libstdc++ is built with debug flags (like _GLIBCXX_DEBUG) that remove the noexcept marker from std::exception. This trickles down to your custom_error, making it not is_nothrow_copy_constructible.

Fixing the cert-err60-cpp Warning

If you want to guarantee your custom_error is noexcept copy constructible (and silence the clang-tidy warning), explicitly define your copy constructor with noexcept:

class custom_error : public std::runtime_error {
public:
    using std::runtime_error::runtime_error;

    // Explicitly default and mark copy operations as noexcept
    custom_error(const custom_error&) noexcept = default;
    custom_error& operator=(const custom_error&) noexcept = default;
};

Just keep in mind: this is only safe if std::runtime_error's copy constructor is actually noexcept in all environments you target. If you ever run on a libstdc++ build where it's not, marking your constructor noexcept will lead to undefined behavior if a copy operation throws.

内容的提问来源于stack exchange,提问作者fcooper8472

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:09:47