C++ 抛出、捕获、作用域stl::string.c_str()异常

C++ 抛出、捕获、作用域stl::string.c_str()异常,c++,exception-handling,scope,C++,Exception Handling,Scope,假设我编写了一些函数myFunc,可以抛出const char*异常: void myFunc() { int returnCode = whatever(); if (!returnCode) { std::string msg; msg.append("whatever function failed"); std::cerr << msg << std::endl; // print warni

假设我编写了一些函数myFunc,可以抛出const char*异常:

void myFunc()
{
    int returnCode = whatever();
    if (!returnCode)
    {
        std::string msg;
        msg.append("whatever function failed");
        std::cerr << msg << std::endl; // print warning message
        throw msg.c_str(); // throw warning message as exception
    }
}
我意识到这并不是一个很好的异常使用策略:最好抛出并捕获异常类,而不是字符串。但是我对这里涉及的范围很好奇。

msg.str()
返回一个临时的
std::string
。因为临时表在语句末尾被删除
抛出时,
c_str()
返回的字符串内容将变得未定义语句通过异常机制离开作用域而终止

(显然,
const char*
temporary的生存期被延长,以到达
catch
处理程序,但这没有帮助,因为底层缓冲区已经消失了)


抛出
std::string
(即
throw msg.str();
)将起作用,临时的生存期将按预期延长。

msg.str()
返回临时的
std::string
。因为临时表在语句末尾被删除
抛出时,
c_str()
返回的字符串内容将变得未定义语句通过异常机制离开作用域而终止

(显然,
const char*
temporary的生存期被延长,以到达
catch
处理程序,但这没有帮助,因为底层缓冲区已经消失了)


抛出
std::string
(即
throw msg.str();
)将起作用,临时对象的生存期将按预期延长。

事实上,
c\u str()
调用正在作用于临时(
string
)对象,当您捕获它时,指针将无效

不仅如此,由于
stringstream
string
可以进行分配,您需要确保不会因为堆问题而抛出。如果由于内存不足而处于该状态,那么在创建异常时可能会更糟。您通常希望在异常情况下避免堆分配

您是否无法使用say
runtime\u error
或创建自己的异常类型?

实际上,
c\u str()
调用正在作用于临时(
string
)对象,当您捕捉到它时,指针将无效

不仅如此,由于
stringstream
string
可以进行分配,您需要确保不会因为堆问题而抛出。如果由于内存不足而处于该状态,那么在创建异常时可能会更糟。您通常希望在异常情况下避免堆分配


您是否无法使用say
runtime\u error
或创建自己的异常类型?

请注意,如果您说过:

throw "error";

您可以,因为字符串文本的生存期就是程序的生存期。但无论如何,不要这样做

注意,如果你说:

throw "error";

您可以,因为字符串文本的生存期就是程序的生存期。但无论如何,不要这样做

Alexander Gessler在中没有提到的一点是,在创建临时字符串对象的过程中可能出现

std::exception
保证在构造期间不会抛出异常,
std::string
没有这样的保证

另一种方法(对于类)是在类中声明私有
std::string
对象。在抛出
之前汇编错误消息,然后抛出
c_str()
。这将抛出一个
const char*
异常,错误消息在该类抛出下一个异常之前一直有效(这可能会再次修改错误字符串)


这里可以找到一个简单的例子:

Alexander Gessler在中没有提到的一点是,在创建临时字符串对象的过程中可能出现

std::exception
保证在构造期间不会抛出异常,
std::string
没有这样的保证

另一种方法(对于类)是在类中声明私有
std::string
对象。在抛出
之前汇编错误消息,然后抛出
c_str()
。这将抛出一个
const char*
异常,错误消息在该类抛出下一个异常之前一直有效(这可能会再次修改错误字符串)


这里可以找到一个简单的例子:

对不起,我的示例程序不够集中,因为它除了使用
字符串
之外还使用了
ostringstream
。我将其修改为仅使用
字符串
,因此我们可以忽略使用
ostringstream
的含义。谢谢临时文件的生存期不会延长,但是由于
throw
ing复制了正在抛出的内容,所以这不是问题。(当抛出一个
char常量*
时,当然,复制的只是指针,而不是它指向的对象。)@Mike Clark建议基本上是一样的-宁愿抛出
std::string
。只有当它指向静态分配的内存区域时,才可以安全地使用
const char*
,该内存区域在catch站点仍然有效<因此,代码>抛出“which function failed”
就可以了。如果临时
std::string
对象的创建引发了异常,该怎么办?请参阅我的答案(以及建议的解决方案)。很抱歉,我的示例程序不够集中,因为它除了使用
字符串之外还使用了
ostringstream
。我将其修改为仅使用
字符串
,因此我们可以忽略使用
ostringstream
的含义。谢谢临时文件的生存期不会延长,但因为
throw
ing会复制正在执行的内容