核心:
我们在写程序的时候应该避免返回handles,References、指针和迭代器统统都是所谓的handles,(号码牌,用来取得某个对象),而返回一个“代表对象内部数据”的handle,随之而来的便是“降低对象封装性”的风险,同时,一如稍早所见,他也可能导致“虽然调用const成员函数但是却造成了对象状态被改变”。
这个条款的遵循有利于增加封装性,帮助const成员函数的行为像一个const,并将发生“虚吊号码牌”(dangling handles)的可能性降至最低。
虚吊号码牌:dangling handles,也就是说handle还存在的情况下,handle所指之物已经被销毁了。
为异常安全的努力是值得的。
当异常被抛出时,带有异常安全性的函数:
1.不泄露任何资源
2.不允许数据败坏
异常安全函数提供以下三个保证之一:
1.基本承诺:如果异常被抛出,程序内的任何事物仍然保持在有效的状态下。没有任何对象或数据结构会因此而败坏,所有对象都处于一种内部前后一致的状态。
2.强烈保证:如果异常被抛出,程序状态不改变.调用这样的函数需有这样的认知:如果函数成功,就是完全成功,如果函数失败,程序会回复到“调用函数之前”的状态。
3.不抛掷保证,承诺绝不抛出异常,因为他们总是能够完成它们原先承诺的功能。
inline函数的使用
1)将大多数的inlining限制在小型、被频繁调用的函数身上,这可以使日后的调试过程和二进制升级更容易,也可以使潜在的代码膨胀问题最小化,使程序速度的提升机会最大化。
不要讲所有函数都声明为inline,要慎重的使用inline函数。平均而言一个程序往往将80%的执行时间花费在20%的代码上。所以你需要找对这20%的代码然后将其瘦身,以大大提高程序的运行效率。
2)不要只因为function template出现在头文件,就将他声明为inline。
3)很多时候,我们都倾向于把类的构造函数,析构函数设为内联函数,但这并不是一个好主义。因为很多看似简短的构造函数身后,隐藏着编译器为你默默填写的大量的函数,尤其是在继承派生体系中。
具体:
为什么我们要使用inline关键字呢?她的效果是什么?
C中定义的宏可以在预编译的时候实现代码替换,没有参数压栈,代码生成,因此运行速度很快,但是也存在一些问题。
如:参数的有效性检查以及返回值类型的有效转换,同时宏定义替换时由于括号的设置不合理可能会出现很多意想不到的问题,在C++中,由于面向类的设计问题更加突出,对protected以及private变量的访问限制了宏定义的功能,因此需要使用新的技术来解决这个问题,inline应运而生。
使用inline并不是万能之道,因为使用inline可能会增加你的object code 大小,频繁使用inline并不是我们所推荐的行为,因为这样做可能会导致代码膨胀,致使内存发生频繁的换页行为,降低指令高速缓存装置的命中率降低,从而导致效率的降低。
1)inline只是对编译器的一个申请,编译器可以拒绝的,并不是强制指令。这项申请可以隐喻提出,也可以显示提出。对于virtual函数的调用一定不会是inlined的,因为virtual意味着多态,直到运行的时候再决定调用哪个函数,而inline意味着执行之前,先将调用动作替换为被调用函数的本体,如果编译器不知道调用哪个函数,你就很难责备编译器拒绝你的inline请求。同时编译器通常不会对“通过函数指针而进行的调用”实施inlining,同时构造函数和析构函数往往是inlining的糟糕候选人,参考如下代码:
class Base {
public:
...
private:
std::string bm1,bm2;
}
class Derived:public Base
{
public:
Derived(){};
private:
std::string dm1,dm2,dm3;
}
由于基类和子类的构造函数都是空的,在初始化之后会向构造函数中添加很多很多代码,因此不建议将其声明为inline。
2)在调用内联函数的过程中,要保证内联函数被编译器看到,通常需要将内联函数的定义放在头文件中。因为大多数建制环境在编译过程中进行inlining,而为了将一个“函数调用”替换为“被调用函数的本体”,编译器必须知道函数长什么样样子。
- 隐式是指在C++类中定义的函数都会被编译器优化为inline函数
class Person{
public:
int age() const //class中定义的函数隐式被编译器声明为inline。
{
return theAge;
}
private:
int theAge;
}
2.显式是指在C++类中声明在类外面定义的函数,我们如果需要inline的话需要自己进行inline的显示声明。
在设计程序的时候,我们需要考虑“将函数声明为inline”的冲击,inline函数无法随着程序库的升级而升级,如果f是程序库的一个inline函数,客户已经将“函数本体”编译进程序中,一旦程序库设计者决定改变f,所有用到该f的客户端程序都必须重新编译,这往往不是大家想要的。
参考文档:
https://www.cnblogs.com/jerry19880126/archive/2013/09/08/3308752.html