为什么c++抛出异常的时候可以用左值引用接收右值?
void dowork() {
//throw myexception();
throw - 1;
}
int main() {
try {
dowork();
}
//catch (myexception &e) {//左值引用能接收临时对象?
// cout << "自定义异常" << endl;
//}
catch (int& i) {
cout << "整型异常" << endl;
}
return 0;
//myexception& e2 = myexception();
}
C++允许把右值用左值引用形式接受。这是由于C++采取了异常安全原则,即保证在抛出异常的情况下,程序状态可以保持平衡,而不会发生没有预料到的变动。这样,当出现异常的时候,左值的值就保持不变,右值的值也可以传递,防止函数调用时未经处理就抛出异常,而造成程序运行异常。
不应该使用异常处理做什么?
异常处理看似简单好用,但它需要项目成员严格遵守开发规范,定好什么时候使用异常,什么时候不使用,而不是既使用异常又使用错误码方式。
构造函数可以抛出异常吗?可以而且建议使用异常,因为构造函数没有返回值,所以只能抛出异常,也有另一种办法就是添加一个成员变量标识对象是否构造成功,这种方法那就会额外添加一个返回该返回值的函数,如果定义一个对象数组那就需要对数组每个对象都判断是否构造成功,这种代码不太好。
构造函数抛出异常会产生内存泄漏吗?不会,构造函数抛出异常产生内存泄漏那是编译器的bug,已经在21世纪修复,不要听信谣言。
void f() {
X x; // If X::X() throws, the memory for x itself will not leak
Y* p = new Y(); // If Y::Y() throws, the memory for *p itself will not leak
}
永远不要在析构函数中把异常抛出,还是拿对象数组举例,数组里有多个对象,如果其中一个对象析构过程中抛出异常,会导致剩余的对象都无法被析构,析构函数应该捕获异常并把他们吞下或者终止程序,而不是抛出。
构造函数内申请完资源后抛出异常怎么办?使用智能指针,关于char*也可以使用std::string代替。
#include <memory>
using namespace std;
class SPResourceClass {
private:
shared_ptr<int> m_p;
shared_ptr<float> m_q;
public:
SPResourceClass() : m_p(new int), m_q(new float) { }
// Implicitly defined dtor is OK for these members,
// shared_ptr will clean up and avoid leaks regardless.
};
永远通过值传递方式用throw抛出异常,通过引用传递用catch来捕获异常。
可以抛出基本类型也可以抛出对象,啥都可以
catch(...)可以捕获所有异常
catch过程中不会触发隐式类型转换
异常被抛出,但是直到main函数也没有被catch,就会std::terminate()
c++不像java,不会强制检查异常,throw了外层即使没有catch也会编译通过
异常被抛出时,在catch之前,try和throw之间的所有局部对象都会被析构
如果一个成员函数不会产生任何异常,可以使用noexcept关键字修饰
通过throw可以重新抛出异常
int main()
{
try {
try {
throw 20;
}
catch (int n) {
cout << "Handle Partially ";
throw; //Re-throwing an exception
}
}
catch (int n) {
cout << "Handle remaining ";
}
return 0;
}