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

构造std::exception时传入c_str()是否安全?该异常处理方式是否合理

在构造std::exception时传入std::string的c_str()是否安全?

首先,从C++标准的合规实现来看,这种操作是安全的。标准规定std::exception的explicit exception(const char* what_arg)构造函数会将传入的字符串内容拷贝到自身内部存储中,what()返回的指针指向这份内部拷贝,而非原始std::string的c_str()指针。即便原始的std::string对象(比如代码里的message)在抛出异常后被销毁,std::exception对象仍能通过what()返回有效的错误信息。

唯一的例外是非常老旧的编译器/标准库实现(比如C++11之前的非合规版本),这类实现可能仅保存指针而不拷贝内容,此时原始std::string析构后,what()会返回野指针,引发未定义行为。但现代主流编译器(GCC、MSVC、Clang)的标准库都严格遵循标准,不会出现这个问题。

这种异常处理方式是否属于不良实践?

属于不推荐的实践,原因如下:

  • 冗余且不够直观:std::exception是标准异常体系的基类,并非为携带自定义错误信息设计。C++标准库提供了std::runtime_error、std::logic_error及其派生类(如std::invalid_argument),这些类的构造函数直接支持传入std::string,无需手动调用c_str(),代码更简洁。
  • 按值捕获的效率与切片问题:你的代码中catch (std::exception ex)是按值捕获,会触发异常对象的拷贝,不仅效率低下,若后续改用std::exception的派生类抛出异常,按值捕获还会丢失派生类的特有信息(切片问题)。正确做法是按const引用捕获。
  • 语义模糊:直接抛出std::exception无法区分错误类型(比如运行时错误还是逻辑错误),而使用std::runtime_error等派生类能清晰表达错误语义,方便调用者针对性处理不同异常场景。
改进后的代码示例
#include <iostream>
#include <stdexcept> // 需包含此头文件以使用std::runtime_error

int main()
{
    try {
        std::string message = "! Something went wrong.";
        throw std::runtime_error(message); // 直接传入std::string,无需c_str()
    }
    catch (const std::exception& ex) { // 按const引用捕获,避免拷贝与切片
        std::cerr << ex.what() << std::endl;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 14:05:39