Effective C++ 阅读笔记(一)透彻了解inline以及降低编译依存关系

简介:

1.类似于C中的#define

  在C++中,提供了inline函数来代替C中的宏定义。(通常可以使用const来代替单纯变量的宏定义,它可以提供类型检查。对于形似函数的宏,最好改用inline函数来替换宏定义。)

  编译器最优化机制通常被设计用来浓缩那些“不含函数调用“的代码,所以当你inline某个函数时,或许编译器就因此有能力对它执行语境相关最优化。

2.效率问题

  inline函数同#define宏定义一样,都是以函数本体做替换,这样做可能增加你的目标码(object code),从而可能造成代码膨胀(代码膨胀会导致额外的换页行为,降低指令高速缓存装置的击中率,带来效率损失)。

  如果inline函数本体很小,编译器针对“函数本体”所产生的码可能比针对“函数调用”所产生的码可能更小。

3.是申请,而不是强制,也不一定要带inline

  注意,inline只是对编译器的一个申请,不是强制命令。这项申请可以隐喻提出,也可以明确提出:

class person{
public:
    int age() const { return  m_age; } //隐喻提出inline申请
private:
    int m_age;
};

4.虚函数可以inline吗?

  大部分编译器都回拒绝太复杂的inline函数,而对所有的virtual虚函数都不能申请为inline函数,这是因为虚函数意味着”等待,直到运行期间才能确定调用哪个函数“,而inline意味着”执行前,先将调用动作替换为函数本体“。

5.构造函数和析构函数一般不应该是inline的

  通常在继承类中,即使是空的构造函数和析构函数,也会调用基类的构造函数和析构函数,如果是多重继承的话代码就会更加复杂。这样如果再把它设为inline函数的话,出现的地方都回替换函数本体,那代码量务必会增加的。

6.templates函数不一定要inline

  templates通常放在头文件中,编译器将它具现化才能知道函数本体的内容。inline需要成本,所以要多加考虑,否则可能导致代码膨胀。

7.程序升级与inline函数

  inline函数无法随程序库的升级而升级,故需要升级的函数不要采用inline函数。

  假如f是一个inline函数,这时如果把f编进程序中,一旦程序决定修改f函数,所有用到f的客户端程序都必须重新编译,这往往是不被接受的。如果是非Inline函数,一旦它有修改升级,程序只需要编译这部分重新连接就好。

 

降低文件间的编译依存关系

  C++没有把接口从实现中分离出来,为了实现接口与实现的分离,要使用声明式,不要使用定义式。基于此构想的两个手段是handle classes和interface classes。

int main()
{
    int x;
    Person p(params);
}

  当编译器看到x的定义式,它知道必须分配多少内存才能够容下一个int。但当编议器看到p的定义式,如何知道一个person有多大?唯一的办法就是询问class的定义式。然而如果class定义式不列出实现的细节,该怎么办?

int main ()
{
    int x;
    Person *p;
}

  只定义一个指向Person对象的指针。这里将不需要class的定义式,如果class Person的任何修改都不需要从新编译这个函数文件。

  也就是说,通过声明的依赖性替代定义的依赖性,来实现接口与实现的分离。

 

所以需要注意

如果使用object reference或object pointers能完成的任务,就不要使用object。references 和pointers只依靠类型声明式,但object就要依靠类型的定义式了。

  如果可以,尽量以class声明式替换class定义式。

 

不知道从何时开始,在这里记笔记已经成为了一个习惯,不记下来总觉得就忘记了

本文转自cococo点点博客园博客,原文链接:http://www.cnblogs.com/coder2012/archive/2013/06/07/3118363.html,如需转载请自行联系原作者

相关文章
|
3月前
|
自然语言处理 编译器 C语言
为什么C/C++编译腰要先完成汇编
C/C++ 编译过程中先生成汇编语言是历史、技术和实践的共同选择。历史上,汇编语言作为成熟的中间表示方式,简化了工具链;技术上,分阶段编译更高效,汇编便于调试和移植;实践中,保留汇编阶段降低了复杂度,增强了可移植性和优化能力。即使在现代编译器中,汇编仍作为重要桥梁,帮助开发者更好地理解和优化代码。
73 25
为什么C/C++编译腰要先完成汇编
|
5月前
|
自然语言处理 编译器 Linux
告别头文件,编译效率提升 42%!C++ Modules 实战解析 | 干货推荐
本文中,阿里云智能集团开发工程师李泽政以 Alinux 为操作环境,讲解模块相比传统头文件有哪些优势,并通过若干个例子,学习如何组织一个 C++ 模块工程并使用模块封装第三方库或是改造现有的项目。
557 56
|
5月前
|
自然语言处理 编译器 Linux
|
6月前
|
存储 程序员 编译器
简述 C、C++程序编译的内存分配情况
在C和C++程序编译过程中,内存被划分为几个区域进行分配:代码区存储常量和执行指令;全局/静态变量区存放全局变量及静态变量;栈区管理函数参数、局部变量等;堆区则用于动态分配内存,由程序员控制释放,共同支撑着程序运行时的数据存储与处理需求。
353 22
|
6月前
|
Linux 编译器 C语言
Linux c/c++之多文档编译
这篇文章介绍了在Linux操作系统下使用gcc编译器进行C/C++多文件编译的方法和步骤。
93 0
Linux c/c++之多文档编译
|
2月前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
12天前
|
编译器 C++ 容器
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
46 12
|
1月前
|
设计模式 安全 C++
【C++进阶】特殊类设计 && 单例模式
通过对特殊类设计和单例模式的深入探讨,我们可以更好地设计和实现复杂的C++程序。特殊类设计提高了代码的安全性和可维护性,而单例模式则确保类的唯一实例性和全局访问性。理解并掌握这些高级设计技巧,对于提升C++编程水平至关重要。
53 16
|
1月前
|
编译器 C++
类和对象(中 )C++
本文详细讲解了C++中的默认成员函数,包括构造函数、析构函数、拷贝构造函数、赋值运算符重载和取地址运算符重载等内容。重点分析了各函数的特点、使用场景及相互关系,如构造函数的主要任务是初始化对象,而非创建空间;析构函数用于清理资源;拷贝构造与赋值运算符的区别在于前者用于创建新对象,后者用于已存在的对象赋值。同时,文章还探讨了运算符重载的规则及其应用场景,并通过实例加深理解。最后强调,若类中存在资源管理,需显式定义拷贝构造和赋值运算符以避免浅拷贝问题。
|
1月前
|
存储 编译器 C++
类和对象(上)(C++)
本篇内容主要讲解了C++中类的相关知识,包括类的定义、实例化及this指针的作用。详细说明了类的定义格式、成员函数默认为inline、访问限定符(public、protected、private)的使用规则,以及class与struct的区别。同时分析了类实例化的概念,对象大小的计算规则和内存对齐原则。最后介绍了this指针的工作机制,解释了成员函数如何通过隐含的this指针区分不同对象的数据。这些知识点帮助我们更好地理解C++中类的封装性和对象的实现原理。

热门文章

最新文章

下一篇
oss创建bucket