C++:链接库和添加包含目录之间的区别

Set*_*ron 37 c++ compiler-construction linker

相当多的标题总结了它.

如果我想使用库,我不确定两者之间的区别.

谢谢!

Mat*_*lia 51

一般来说,你需要两者.

包含文件包含类型的声明,inline函数的原型,函数,#defines,......,通常是编译器在编译文件时需要注意的库的每个信息.

相反,静态库包含库函数的实际目标代码.如果头部包含原型,则静态库包含函数的(已编译)定义,即链接器将与您链接的对象模块.

如果您只包含头文件而不链接静态库,则链接器会抱怨缺少定义,因为您将使用标头中声明的函数,但未在任何位置定义(=没有实现).另一方面,如果您只链接静态库而不提供标题,编译器会抱怨未知标识符,因为它不会对您正在使用的库符号有任何线索.

这个概念与编译多文件项目时的概念非常相似:要访问在其他项目中编写的定义,.cpp您需要只包含带有声明的头文件,最后的链接器将各种对象模块链接在一起.

就dll而言,通常提供导入库 ; 导入库就像静态库,但是,它们不包含库的所有代码,而是包含将函数调用到dll中的小存根.每次在一个目标模块中遇到对库函数的调用时,链接器会将其定向到存根,存根又将其重定向到代码中的dll 1.总而言之,在Windows上处理dll时,你通常有一个.h(prototypes/...),一个.lib(你链接的导入库,包含存根)和一个.dll(包含库的实际代码的动态链接库).

顺便说一下,有些库只是"标题"(你可以在boost中找到很多),这意味着它们的所有代码都被放入一个标题中,因此不需要静态库.这些库通常只由内联代码(函数/类/ ...)和模板组成,因此不需要单独的定义.

通常这样做是因为静态库是丑陋的野兽,原因如下:

  • 你必须明确地与他们联系;
  • 因为它们直接链接到你的代码,所以它们必须使用完全相同的C/C++运行时库,这意味着,至少在Windows上,分配静态库(不同的编译器,不同的编译器版本,不同的配置)是不切实际的.编译器使用不同的标准库,为这些方面的每个组合分配静态库至少是不切实际的;
  • 因此,一般来说,你必须首先编译自己的静态库版本,然后链接它.

将所有这些与仅包含头文件进行比较... :)


  1. 实际上,现代工具链可以识别这些存根并避免额外的间接步骤.有关详细信息,请参阅Raymond Chen的本系列.


Fer*_*yer 23

编译器需要知道包含目录,因为它需要包括头部(界面要使用库)文件.

连接器需要知道库目录,因为它需要你的可执行文件链接到(预编译)实现图书馆.

另请参见编译器和链接器之间的区别是什么?