effective c++:inline函数,文件间编译依存关系
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函数,文件间编译依存关系的更多相关文章
- [Effective C++ --031]将文件间的编译依存关系降至最低
引言:编译时间成本 在项目中我们都会碰到修改既存类的情况:某个class实现文件做了些轻微改变,修改的不是接口,而是实现,而且只改private成分. 重新build这个程序,并预计只花数秒就好,当按 ...
- 读书笔记_Effective_C++_条款三十一:将文件间的编译依存关系降至最低(第三部分)
下面来谈谈书中的第二部分,用Interface Classes来降低编译的依赖.从上面也可以看出,避免重编的诀窍就是保持头文件(接口)不变化,而保持接口不变化的诀窍就是不在里面声明编译器需要知道大小的 ...
- Effective C++ -----条款31:将文件间的编译依存关系降至最低
支持“编译依存性最小化”的一般构想是:相依于声明式,不要相依于定义式.基于此构想的两个手段是Handle classes 和 Interface classes. 程序库头文件应该以“完全且仅有声明式 ...
- 条款31:将文件间的编译依存关系降至最低(Minimize compilation dependencies between files)
NOTE1: 1.支持“编译依存性最小化”的一般构想是:相依于声明式,不要相依于定义式.基于此构想的两个手段是Handle classes 和 Interface classes. 2.程序库头文件应 ...
- [EffectiveC++]item31:将文件间的编译依存关系降至最低
P143:“声明的依赖性"替换“定义的依存性”
- npm install含义 及vue安装启动项目时报错解决及vue建项目时各文件间的依赖关系
全局安装vue-cli,使用命令npm install -g vue-cli. 下载模板代码,使用命令vue init webpack my-project,之后会有一些询问,按需填写即可. 最后会看 ...
- c++将文件之间编译关系降到最低
类的定义式:类的定义,可以知道类的大小 类的实现: 类的声明:类的声明,表明,使用此类,编译不会出错 C++并没有把“将接口从实现中分离”做得很好.Class的定义式不只详细叙述了Class接口,还包 ...
- 类间调用inline函数的效率
问题描述: class A { public: int x, y, k, NY; inline int f(int i, int j, int k) {return ((i)*(NY + 1) * ...
- C++的优秀特性2:inline 函数
(转载请注明原创于潘多拉盒子) Inline函数是C++的一个很小的特性,在不计较效率的情况下,这个特性似乎可有可无.然而,C++天生是为最为广泛的应用场景设计的,因此,总会有关于效率的问题.其实,除 ...
随机推荐
- USACO Section 2.2: Subset Sums
dp题,一碰到dp我基本就是跪,搜了网上的答案分两种,一维和二维. 先讲二维,sum[i][j]表示前i个数的subset里差值为j的分法数量.当加入数字i时,有两种选择,某一个set和另外一个set ...
- DataGridView中的单元格提示错误信息
http://stackoverflow.com/questions/7713988/winforms-problems-validating-a-cell-in-a-datagridview
- JAVA设计模式之【工厂方法模式】
看例子 1.TV产品接口,负责播放 public interface TV // TV接口 { public void play(); } 2.TV工厂接口,负责生产产品 public interfa ...
- java.lang.InstantiationException: DWR can't find a spring config. See the logs for solutions
在spring整合dwr时,报找不到配置文件 DWRcan't find a spring config. See the logs for solutions 解决办法: 在web.xml中添加一下 ...
- D:/apache2/conf/httpd.conf:Cannot load D:/apache2/modules/mod_actions.so
报错如下: errors reported here must be corrected before service can be started.httpd:Syntax error on lin ...
- Qt之QHeaderView排序
简述 在Windows中我们经常会遇到表头排序,比如可以对文件按照名称.修改日期.类型.大小进行排序,方便我们统一的归类查找. Qt中,我们可以通过点击表头来对QTableView或QTreeView ...
- HDU 1074 Doing Homework
第一次做这道题大概是半个月前了吧,状压DP一个很新鲜的名词 当时看题解怎么也看不懂,现在看懂了以后还是很简单的 所谓状态压缩就是用一个整数的二进制来表示一个状态,比如有三个作业 000表示一科作业也没 ...
- 浅谈 Scala 中下划线的用途
Scala 作为一门函数式编程语言,对习惯了指令式编程语言的同学来说,会不大习惯,这里除了思维方式之外,还有语法层面的,比如 underscore(下划线)就会出现在多种场合,令初学者相当疑惑,今天就 ...
- [转]使用 jQuery Mobile 与 HTML5 开发 Web App —— jQuery Mobile 事件详解
在前文<使用 jQuery Mobile 与 HTML5 开发 Web App —— jQuery Mobile 默认配置与事件基础>中,Kayo 对 jQuery Mobile 事件的基 ...
- HDU 5316 Magician (线段树,单值修改,微变形)
题意:给一个初始序列A[1,n],第j个数字代表精灵j的power值,有两种操作:(1)查询区间[L,R] (2)修改某个精灵的power值. 但,查询的是区间[L,R]中一个美丽子序列sub[l,r ...