inline函数

inline函数可以不受函数调用所带来的额外开销,编译器也会优化这些不含函数调用的代码,但是我们不能滥用Inline函数,如果程序中的每个函数都替换为inline函数那么生成的目标文件会急剧增加,当我们运行这个程序时会占用机器大量的内存,所以我们一般把本体很小的函数替换为Inline(一般10行以内)。

inline只是对编译器的申请,并不是强制执行,比方在class定义式内定义成员函数,如下所示

class Person {
public:
  ...
  int age() const { return theAge; } // an implicit inline request: age is
  ... // defined in a class definition
private:
  int theAge;
};

age()便被隐喻声明为inline.

而对于virtual函数,由于他需要在运行时决定调用哪个函数,所以即便是声明虚函数为Inline,编译器也会拒绝这个请求。

在构造函数和析构函数上使用Inline貌似可行,因为他们的函数体大多不长,甚至不含代码,但是这往往是个假象。

Derived::Derived() // conceptual implementation of
{ // “empty” Derived ctor
  Base::Base(); // initialize Base part
  try { dm1.std::string::string(); } // try to construct dm1
  catch (...) { // if it throws,
    Base::~Base(); // destroy base class part and
    throw; // propagate the exception
  }
  try { dm2.std::string::string(); } // try to construct dm2
  catch(...) { // if it throws,
    dm1.std::string::~string(); // destroy dm1,
    Base::~Base(); // destroy base class part, and
    throw; // propagate the exception
  }
  try { dm3.std::string::string(); } // construct dm3
  catch(...) { // if it throws,
    dm2.std::string::~string(); // destroy dm2,
    dm1.std::string::~string(); // destroy dm1,
    Base::~Base(); // destroy base class part, and
    throw; // propagate the exception
  }
}

这就是所谓空的构造函数实际产生的代码,它一定会调用成员变量和base构造函数等。

对于需要调试的程序,Inline函数的存在会对调试造成很大障碍,毕竟断电不能设在并不存在的函数内。

所以对于Inline函数一开始设计程序时尽量少的使用,当有需求时再使用也不迟。

文件间编译依存关系

当我们对c++程序的某个实现文件做了轻微的修改,然后重新建置这个程序,并预计只花数秒就好,当按下“Build”或键入make,整个项目都被重新编译连接了。这个问题出在c++并没有将接口与实现分离。

#include <string>
#include "date.h"
#include "address.h" class Person {
public:
  Person(const std::string& name, const Date& birthday,
  const Address& addr);
  std::string name() const;
  std::string birthDate() const;
  std::string address() const;
  ...
private:
  std::string theName; // implementation detail
  Date theBirthDate; // implementation detail
  Address theAddress; // implementation detail
};

如同上述类的定义,如果这些头文件被修改,那么含入它的文件也一定会被重新编译,这就造成了文件间的编译依存关系。

class Date; // forward declaration
class Address; // forward declaration
class Person {
public:
  Person(const std::string& name, const Date& birthday,
  const Address& addr);
  std::string name() const;
  std::string birthDate() const;
  std::string address() const;
  ...
};

我们可以通过前置声明使得Person只有在Person头文件被修改时才被重新编译。但他同样存在问题

int main()
{
  int x; // define an int
  Person p( params ); // define a Person
  ...
}

当编译器看到p时就必须给他分配足够放Person的空间,它也只有访问类的定义式来获取这一信息,我们需要将对象的实现隐藏于指针背后。书中对于这一问题提出了两种设计方案:handle classes和interface classes。对于这两中实现比较陌生,所以等以后透彻理解它们之后再补充本文。

effective c++:inline函数,文件间编译依存关系的更多相关文章

  1. [Effective C++ --031]将文件间的编译依存关系降至最低

    引言:编译时间成本 在项目中我们都会碰到修改既存类的情况:某个class实现文件做了些轻微改变,修改的不是接口,而是实现,而且只改private成分. 重新build这个程序,并预计只花数秒就好,当按 ...

  2. 读书笔记_Effective_C++_条款三十一:将文件间的编译依存关系降至最低(第三部分)

    下面来谈谈书中的第二部分,用Interface Classes来降低编译的依赖.从上面也可以看出,避免重编的诀窍就是保持头文件(接口)不变化,而保持接口不变化的诀窍就是不在里面声明编译器需要知道大小的 ...

  3. Effective C++ -----条款31:将文件间的编译依存关系降至最低

    支持“编译依存性最小化”的一般构想是:相依于声明式,不要相依于定义式.基于此构想的两个手段是Handle classes 和 Interface classes. 程序库头文件应该以“完全且仅有声明式 ...

  4. 条款31:将文件间的编译依存关系降至最低(Minimize compilation dependencies between files)

    NOTE1: 1.支持“编译依存性最小化”的一般构想是:相依于声明式,不要相依于定义式.基于此构想的两个手段是Handle classes 和 Interface classes. 2.程序库头文件应 ...

  5. [EffectiveC++]item31:将文件间的编译依存关系降至最低

    P143:“声明的依赖性"替换“定义的依存性”

  6. npm install含义 及vue安装启动项目时报错解决及vue建项目时各文件间的依赖关系

    全局安装vue-cli,使用命令npm install -g vue-cli. 下载模板代码,使用命令vue init webpack my-project,之后会有一些询问,按需填写即可. 最后会看 ...

  7. c++将文件之间编译关系降到最低

    类的定义式:类的定义,可以知道类的大小 类的实现: 类的声明:类的声明,表明,使用此类,编译不会出错 C++并没有把“将接口从实现中分离”做得很好.Class的定义式不只详细叙述了Class接口,还包 ...

  8. 类间调用inline函数的效率

    问题描述: class A { public: int x, y, k, NY; inline int f(int i, int j, int k)  {return ((i)*(NY + 1) * ...

  9. C++的优秀特性2:inline 函数

    (转载请注明原创于潘多拉盒子) Inline函数是C++的一个很小的特性,在不计较效率的情况下,这个特性似乎可有可无.然而,C++天生是为最为广泛的应用场景设计的,因此,总会有关于效率的问题.其实,除 ...

随机推荐

  1. android:screenOrientation的说明 固定屏幕显示方向

    Activity在屏幕当中显示的方向.属性值可以是下表中列出的一个值: "unspecified" 默认值,由系统来选择方向.它的使用策略,以及由于选择时特定的上下文环境,可能会因 ...

  2. Back to Back Order Process

    Steps involved involved in back to back order process in oracle apps 1. Enter Sales Order 2. Book Sa ...

  3. Maven3路程(五)用Maven创建Hibernate项目

    本文将用Maven3.Hibernate3.6.Oracle10g整合,作为例子. 环境清单: 1.Maven3.0.5 2.Hibernate3.6.5 Final 3.JDK1.7.0.11 4. ...

  4. jquery ajax的async属性的理解

    $(function(){ queryTemplateSort(); // fillAddTemplatePage(); function queryTemplateSort() { $.ajax({ ...

  5. Android开源库--Asynchronous Http Client异步http客户端

    如果说我比别人看得更远些,那是因为我站在了巨人的肩上. github地址:https://github.com/loopj/android-async-http Api文档地址:http://loop ...

  6. Winform——计算器

    namespace 计算器2._0 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } pr ...

  7. 跨平台的神器RAD XE5 来啦!!!! XE5破解

    什么叫真正的跨平台,DELPHI经过这么长时间的洗礼,如今走上了夸平台的开发之路.希望RAD加油! 先去下一个XE5 再去下一个破解神器 一个破解BDS.exe的神器 开始吧.为了成功破解,请先将电脑 ...

  8. js方式进行地理位置的定位api搜集

    新浪 //int.dpool.sina.com.cn/iplookup/iplookup.php?format=js //int.dpool.sina.com.cn/iplookup/iplookup ...

  9. UVa 1595 (水题) Symmetry

    颓废的一个下午,一直在切水题,(ˉ▽ ̄-) 首先如果这些点是对称的话,那么它们的对称轴就是x = m,m是横坐标的平均值. 把这些点放到一个集合里,然后扫描每个点,计算出它关于x = m的对称点,看这 ...

  10. php 换行 PHP_EOL变量

    一个小小的换行,其实在不同的平台有着不同的实现,为什么要这样,可以是世界是多样的. 本来在unix世界换行就用/n来代替,但是windows为了体现他的不同,就用/r/n,更有意思的是在mac中用/r ...