More Effective C++ 读书笔记五——异常

简介: 条款12:了解“抛出一个exception”与“传递一个参数”或“调用一个虚函数”之间的差异 第一,exception object总是会被复制,如果以by value方式捕捉,它们甚至被复制两次。至于传递给函数参数的对象不一定得复制。第二,“被抛出成为exceptions”的对象,其被允许的

条款12:了解“抛出一个exception”与“传递一个参数”或“调用一个虚函数”之间的差异

第一,exception object总是会被复制,如果以by value方式捕捉,它们甚至被复制两次。至于传递给函数参数的对象不一定得复制。第二,“被抛出成为exceptions”的对象,其被允许的类型转换动作,比“被传递到函数去”的对象少。第三,catch子句以其“出现于源代码的顺序”被编译器检查比对,其中第一个匹配成功者便被执行;而当我们以某个对象调用一个虚函数,被选中执行的是那个“与对象类型最佳吻合”的函数。

条款13:以by reference方式捕捉exceptions

上面两个条款都提到了被抛出对象的复制问题,通过下面的几个例子试了下:
[cce lang=”cpp”]
#include <iostream>

static int count = 0;

class e_class {
public:
e_class() {
std::cout << “in constructor: count: ” << ++count << std::endl;
}
e_class(const e_class &right) {
std::cout << “in copy constructor: count: ” << ++count << std::endl;
}
};

int main(){
try {
e_class e_c; //创建对象,调用构造函数count累加
throw e_c; //抛出异常,e_c被复制,调用拷贝构造函数,count累加
} catch (e_class e) { //以by value形式catch,对象再次被复制,count累加
}

return 0;
}
[/cce]
这里count被加了3次,第一次是e_class对象构造的时候,然后抛出去的时候,对象被复制,然后catch的时候因为按值传递,传入对象再次被复制。执行结果为:
in constructor: count: 1
in copy constructor: count: 2
in copy constructor: count: 3
这里能被避免的就是catch这里,如果按照引用传递,这次复制就可以避免:
[cce lang=”cpp”]
#include <iostream>

static int count = 0;

class e_class {
public:
e_class() {
std::cout << “in constructor: count: ” << ++count << std::endl;
}
e_class(const e_class &right) {
std::cout << “in copy constructor: count: ” << ++count << std::endl;
}
};

int main(){
try {
e_class e_c; //创建对象,调用构造函数count累加
throw e_c; //抛出异常,e_c被复制,调用拷贝构造函数,count累加
} catch (e_class &e) { //以by reference形式catch,不会再次被复制
}

return 0;
}
[/cce]
采用按引用方式catch后,和函数按引用传递参数一样,对象不再被复制,执行结果为:
in constructor: count: 1
in copy constructor: count: 2

条款12中还介绍了再次抛出异常的对象复制问题:
[cce lang=”cpp”]
#include <iostream>

static int count = 0;

class e_class {
public:
e_class() {
std::cout << “in constructor: count: ” << ++count << std::endl;
}
e_class(const e_class &right) {
std::cout << “in copy constructor: count: ” << ++count << std::endl;
}
};

int main(){
try {
try {
e_class e_c;
throw e_c;
} catch (e_class &e) {
throw e; //这里抛出的是e的副本,会对e进行复制后抛出
}
}catch(…) {
}

return 0;
}
[/cce]
这里在catch子句中重新抛出了异常,但是这种方式抛出的其实是异常对象的副本,对象会再次被复制,执行结果为:
in constructor: count: 1
in copy constructor: count: 2
in copy constructor: count: 3
如果改成这样:
[cce lang=”cpp”]
#include <iostream>

static int count = 0;

class e_class {
public:
e_class() {
std::cout << “in constructor: count: ” << ++count << std::endl;
}
e_class(const e_class &right) {
std::cout << “in copy constructor: count: ” << ++count << std::endl;
}
};

int main(){
try {
try {
e_class e_c;
throw e_c;
} catch (e_class &e) {
throw; //直接抛出e,不会进行复制
}
}catch(…) {
}

return 0;
}
[/cce]
这里throw语句不带任何参数,抛出的是当前异常本身,当前的异常对象不会再次被复制,执行结果为:
in constructor: count: 1
in copy constructor: count: 2


转载自:https://coolex.info/blog/267.html

目录
相关文章
|
27天前
|
安全 程序员 编译器
【C++】异常
C++异常处理机制允许在程序运行时出现错误时,通过`try`、`catch`和`throw`关键字将错误信息传递回调用栈,进行异常处理。它支持异常的重新抛出、自定义异常体系以及标准库提供的异常类层次结构,如`std::exception`及其派生类。异常处理提高了代码的健壮性和可维护性,但也带来了性能开销和代码复杂性等问题。合理使用异常机制,可以有效提升程序的稳定性和安全性。
44 3
|
6月前
|
编译器 C++
c++primer plus 6 读书笔记 第十章 对象和类
c++primer plus 6 读书笔记 第十章 对象和类
|
6月前
|
编译器 C++
《Effective C++ 改善程序与设计的55个具体做法》 第一章 笔记
《Effective C++ 改善程序与设计的55个具体做法》 第一章 笔记
|
6月前
|
编译器 数据安全/隐私保护 C++
c++primer plus 6 读书笔记 第十三章 类继承
c++primer plus 6 读书笔记 第十三章 类继承
|
5月前
|
C++
C++ 异常机制问题之捕获异常的问题如何解决
C++ 异常机制问题之捕获异常的问题如何解决
|
5月前
|
安全 Java 程序员
【C++11】异常知多少
【C++11】异常知多少
54 7
|
4月前
|
安全 Java 程序员
|
6月前
|
C++
c++primer plus 6 读书笔记 第十四章 C++中的代码重用
c++primer plus 6 读书笔记 第十四章 C++中的代码重用
|
6月前
|
C++
c++primer plus 6 读书笔记 第十一章 使用类
c++primer plus 6 读书笔记 第十一章 使用类
|
6月前
|
编译器 C++
c++primer plus 6 读书笔记 第八章 函数探幽0
c++primer plus 6 读书笔记 第八章 函数探幽0