可能重复:
Inline functions in C++
如果我在其头文件中完全实现一个类,编译器会做什么?一个典型的例子如下:
class MyException
{
public:
explicit MyException(const char* file, int line) file(file), line(line) {};
const char* getFile() const { return file };
int getLine() const { return line };
private:
const char* const file;
const int line;
};
我的目的是使用这样的课程:throw MyException(__FILE__, __LINE__)
。
我将此头文件包含在每个.cpp文件中。我想编译器将按照定义的次数编译该类,并将(相同的)机器代码包含在它生成的每个目标文件中。现在,链接器会做什么?我尝试了一个更简单的例子(没有所有那些讨厌的const
)并且编译得很好。
如果不是简单的类,我在头文件中实现了一个三屏长的C函数会发生什么?最后一个问题,我应该将我的例子分成.h和.cpp文件吗?
答案 0 :(得分:3)
类定义本身不会产生任何代码。它只是向类的用户显示它是如何布局的,因此他们可以生成适当的代码来操作它。
这是生成代码的类的成员函数。在类定义中定义成员函数时,它为函数提供隐式inline
声明。
可以通过以下两种方式之一编译和链接函数调用:
(1)可以在图像中放置一个带有RETURN汇编指令的功能代码的单个副本,并且可以在呼叫站点放置CALL汇编指令(以及param传递和返回值传输)将控制转移到此代码。
或
(2)函数实现的整个副本可以替换调用站点上的整个函数调用。
声明为inline
的函数是建议编译器以第二种方式执行此操作。此外,inline
声明允许在多个转换单元中定义函数(因此可以将其放在共享头文件中)。为了使编译器可以选择实现第二种方法,它需要在编译时获得函数实现的副本。如果函数实现位于外部翻译单元中,则不可用。
还应该注意的是,现代编译器使用内联声明的函数来做复杂的事情。参见:
答案 1 :(得分:3)
所有方法都是内联方法。你可能会在整个编译过程中失去一些时间,但没关系。据我所知,知道唯一可能出现的问题是你有一个静态的非成本成员变量。然后你必须为它分配一个存储位置(如果你想要的话,放置一个定义和初始值),大概是.cpp
,否则你会得到关于多重定义的链接器错误。
我见过只有标题的项目,它们在CPP中只有main()
函数,但这是很模糊的。
答案 2 :(得分:3)
在头文件中实现成员函数时,所有这些函数都隐式inline
。
这意味着什么?它有什么含义?
按照, C ++ 03标准§7.1.3/ 4:
是的,每个翻译单元都会定义inline
函数。这个可能会导致二进制文件的大小增加。
通常任何好的主流编译器都会在需要时在调用点替换函数体,因此仅为#1标记函数inline
并不是一个好主意,但是如果你想让你的 意图 向您的班级用户清楚,然后您可以通过在标题中定义函数或明确将您的函数标记为inline
来实现。
我应该将我的示例拆分为
.h
和.cpp
个文件吗?
是的,这是大多数项目使用的常用编译模型,其中您将接口(.h)与实现(.cpp)分开。接口与代码用户共享为头文件,而实施以二进制文件的形式提供。若某些范围,这为您的知识产权提供了保障。
这称为 分离模型 。
使用模板的C ++项目通常使用 包含模型 ,而不是通常的C ++项目的分离模型。