Col*_*nee 1 c++ exception undefined-behavior
通过非const引用在try-block中抛出构造在堆栈上的对象,捕获并修改它,然后引用另一个catch块抛出它有什么问题吗?
以下是我所指的内容的简短示例.
struct EC {
EC(string msg) { what = msg; }
string where;
string what;
void app(string& t) { where += t; }
string get() { return what; }
};
try {
try {
try {
EC error("Test");
throw error;
}
catch (EC& e) {
e.app("1");
throw e;
}
}
catch (EC& e) {
e.app("2");
throw e;
}
}
catch (EC& e) {
e.app("3");
cout << e.where << endl;
cout << e.get() << endl;
}
Run Code Online (Sandbox Code Playgroud)
是否有可能导致e.what包含垃圾,但是e.在哪里保持完整?例如:
e.where是"123"
e.get()返回大量垃圾数据,直到碰巧遇到空字节.
没有"通过引用投掷"这样的事情.这根本不可能.这没有语法.每次尝试"抛出引用"时,实际抛出引用对象的副本.不用说,没有尝试在代码中引用引用.
可以通过引用捕获先前抛出的异常(即使是非常量异常)并通过它修改临时异常对象.它会工作.实际上,您可以重新抛出现在修改的现有异常对象,而不是创建新对象.即你可以做到
throw;
Run Code Online (Sandbox Code Playgroud)
代替
throw e;
Run Code Online (Sandbox Code Playgroud)
在你的catch子句中仍然得到正确行为的代码,即原始对象(带有修改)将继续其处理程序层次结构的飞行.
但是,你的代码是不正确的
e.app("1");
Run Code Online (Sandbox Code Playgroud)
调用(和其他调用app),因为参数是非const引用.将app声明更改为
void app(const string& t) { where += t; } // <- either this
void app(string t) { where += t; } // <- or this
Run Code Online (Sandbox Code Playgroud)
为了编译.
否则,您的代码应该可以正常工作.你不应该得到任何垃圾get().如果这样做,则必须是编译器的问题或您未显示的代码.