C++中的throw作用域

3
当我切换编译器时,我信任的旧throw代码(如下面的示例)将失败。我猜测问题可能是err变量的范围?发生的情况是,在尝试访问err的字符串部分时,它已被释放。使用自定义异常类更好的方式是什么?
if (someErrorHappend)
{
    std::stringstream err;
    err << "Some error #" << GetLastError() << ".";
    throw SomeCustomException("MyClass", "MyFunc", err.str().c_str());
}

出了什么问题?异常的第三个参数是做什么用的? - Alan Stokes
1
SomeCustomException 的构造函数需要复制字符串。您只需小心,不要在尝试抛出异常时引发异常。如果使用C++11移动语义正确实现,则不应该有问题。 - Cody Gray
建议:首先列出异常类的要求。它必须携带哪些信息(如果有)?然后编写该类,使用最佳实践编写其构造函数和复制/移动运算符。 从那时起,一切都会自然而然地流动。 - Richard Hodges
1
@RichardHodges: 建议:不要编写任何复制/移动操作符或析构函数(也称为零规则)。 - Matthieu M.
@Matthieu M 是的,那是“最佳实践”的一部分。 - Richard Hodges
1个回答

4

c_str 是一个非拥有指针,因此您不应将其直接传递给会保留它的构造函数。

要解决这个问题,只需调整构造函数 SomeCustomException,使其接受一个 std::string 而不是 char *char * 将被转换为拥有对象的 string

在未来,您可以通过删除 c_str() 调用并仅保留 err.str() 来迁移代码。编译器将应用 C++11 移动语义以消除一次复制操作。

不必担心内存不足。 stringstream 代码已经在堆上为其内部字符串分配了空间,而异常构造函数与此无异——两者都在 throw 之前运行,如果事先已经耗尽内存,则应该已经处于异常处理状态。


这个程序能在 C++03 中正常工作吗?还是拷贝语义只能在 C++11 中使用,因为你明确提到了它 - 我必须支持 C++03。 - user152949
1
@IngeHenriksen 是的,移动语义是一种非破坏性的更改(除了一些病态情况,其中 string 明显不是)。 - Potatoswatter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接