代码示例一:
try {
exception e;
throw e;
} catch(exception& refer)
代码示例二:
exception& method()
{
exception e;
return e;
}
有些书提到代码示例一可以,代码二是错误的,因为e
它是一个局部变量,并且会在函数结束时销毁,但我的问题是为什么示例代码一可以?不是e
局部变量吗?
是的,在示例一中,e
它位于 try 块的本地,并在退出该范围时被销毁。但是当你抛出时,编译器会创建一个副本(或移动),其生命周期会延长到 catch 块的末尾,并且引用refer
所指的是这个副本。
为了弄清楚编译器在这种情况下做了什么,我总是喜欢抽出我的Noisy
类。
#include <iostream>
class Noisy
{
public:
Noisy()
{ std::cout << "Noisy default construct\n"; }
Noisy(Noisy const&)
{ std::cout << "Noisy copy\n"; }
Noisy(Noisy&&)
{ std::cout << "Noisy move\n"; }
~Noisy()
{ std::cout << "Noisy destroy\n"; }
Noisy& operator=(Noisy const&)
{ std::cout << "Noisy copy assign\n"; return *this; }
Noisy& operator=(Noisy&&)
{ std::cout << "Noisy move assign\n"; return *this; }
void swap(Noisy&)
{ std::cout << "Noisy swap\n"; }
};
int main(int argc, char* argv[])
{
try
{
std::cout << "in try block\n";
Noisy n;
std::cout << "about to throw n\n";
throw n;
std::cout << "end of try block\n";
}
catch (Noisy & n)
{
std::cout << "in catch block\n";
}
std::cout << "after catch\n";
}