首页 > 编程语言 >c++ inline

c++ inline

时间:2024-04-13 21:55:05浏览次数:18  
标签:头文件 定义 c++ 编译 inline 链接 函数

当在头文件中定义函数时,如果这个头文件被多个 .cpp 文件包含,那么每个包含该头文件的 .cpp 文件都会有一个该函数的副本。这在链接阶段会引起“多重定义”的错误,因为链接器找到多个相同符号的定义。

使用 inline 关键字可以解决这个问题。当一个函数被声明为 inline,编译器会尝试将该函数的代码直接嵌入到每个调用点,从而消除了函数调用的开销。更重要的是,inline 函数有特殊的链接规则,允许在多个不同的编译单元中定义相同的函数,只要所有的定义都是相同的。这意味着 inline 函数不会引起链接器的多重定义错误。

因此,当你将头文件中的函数声明为 inline 后,即使这个头文件被多个 .cpp 文件包括,每个 .cpp 文件中的 inline 函数副本在编译后都被视为同一函数,避免了多重定义的问题,从而编译链接成功。这也是为什么加上 inline 后就能编译通过的原因。

在C++中,函数是否声明为 inline 影响其链接行为和代码生成方式。这里我们详细解释一下加不加 inline 在链接期的区别:

1. 非 inline 函数

  • 一般定义:非 inline 函数通常在一个 .cpp 文件中定义,且每个函数的定义只能存在于一个编译单元中。
  • 链接行为:如果一个非 inline 函数被定义在多个编译单元中(即在多个 .cpp 文件中重复定义),链接器会报错,提示多重定义(Multiple Definitions)错误。这是因为每个编译单元会生成该函数的一个副本,而链接器在最终链接成一个可执行文件时,无法确定使用哪一个副本。
  • 符号表:在编译结束时,每个非 inline 函数在其编译单元的符号表中都有一个条目。链接器需要检查这些符号以确保每个符号只定义一次。

2. inline 函数

  • 一般定义inline 函数可以在头文件中定义,并且这个头文件可以被多个 .cpp 文件包含。
  • 链接行为inline 函数的多个定义(即使在不同的编译单元中)在链接时被视为同一个函数。这是因为 inline 指示符告诉编译器和链接器,每个定义都是相同的,且可以合并。即便实际的机器代码可能被嵌入到每个调用该函数的地方,编译器也保持了对原始函数定义的一个副本,以用于链接时的符号解析。
  • 弱符号:通常 inline 函数在编译后被视为“弱符号”(Weak Symbols),这意味着如果链接器在多个编译单元中遇到同名的弱符号,它会选择其中一个,并忽略其他的。这样就避免了多重定义的错误。
  • 优化和代码体积inline 函数可以减少函数调用的开销,因为编译器可能将函数体直接插入到调用点。然而,过多的 inline 可能导致代码膨胀,因为每个调用点都有函数体的一个副本。

总结来说,inline 函数在编写库和头文件时非常有用,因为它们允许在多个编译单元中重用相同的函数定义,而不会导致链接错误。这也有助于模板和头文件中的函数的重用,同时允许编译器进行优化,提高程序的运行效率。

标签:头文件,定义,c++,编译,inline,链接,函数
From: https://www.cnblogs.com/nameyouxuan/p/18133441

相关文章

  • 第十五届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组题解
    试题A:握手问题本题总分:\(5\)分思路:组合计数,用为\(50\)个人握手的总方案数\(C^{2}_{50}\),减去七个人彼此没有握手握手的方案数\(C^{2}_{7}\)即为答案。A:握手问题#include<bits/stdc++.h>#defineintlonglong#definedblongdouble#defineall(f)f.begin()......
  • C与C++在函数和数据的比较
    C与C++在函数和数据的比较CData(struct)数据是一个类型->根据数据的类型创建出真正的数据Function函数就是用来处理数据的缺陷:语言没提供关键字.所以数据是全局的->各个函数都可以处理数据C++Data将数据和处理这些数据的函数包裹在一起,其他函数看不到其他函数处理......
  • C++ 键盘操作
    1.单方移动#include<iostream>#include<windows.h>#include<conio.h>usingnamespacestd;intmain(){HANDLEhandle=GetStdHandle(STD_OUTPUT_HANDLE);COORDcoord={0,0};SetConsoleCursorPosition(handle,coord);cout<&l......
  • c++中的查找list元素
    回顾学习find和find_if,网上查了一下资料,这里记录一下。    STL的find,find_if函数提供了一种对数组、STL容器进行查找的方法。使用该函数,需#include<algorithm>我们查找一个list中的数据,通常用find(),例如:1、findusingnamespacestd;intmain(){  list<int>l......
  • c++结构体、共用体(联合体)
    union数据成员共享同一段内存,在使用时按照最大成员变量的大小开辟空间,相对struct比较是节省内存的。内存空间是以占内存最大的以准。 struct数据成员各占一段内存,在使用时按照各自成员变量的大小开辟空间。 如图:一个学生(姓名namechar[10],年龄oldshort,电话telchar[......
  • 通过__cplusplus查看c++版本并检查gcc支持版本
    虽然平时开发都是用的c++11标准,但打算看一下wslubuntu里面的gcc默认支持什么标准~1打印__cplusplus宏#include<cstdio>intmain(){printf("%ld\n",__cplusplus);}➜testg++test_cpp_version.cpp-otest_cpp_version➜test./test_cpp_version20......
  • C++,四种强制类型转换,static_cast,const_cast,dynamic_cast,reinterpret_cast
      #include<iostream>usingnamespacestd;structA{virtualvoidfunc(){cout<<"Afunc"<<endl;}};structB:publicA{voidfunc(){cout<<"Bfunc"<<endl;}};intmain(){c......
  • C++未定义行为
    0前言未定义行为(UndefinedBehavior)是指语言标准未做规定的行为。同时,标准也从没要求编译器判断未定义行为,所以这些行为有编译器自行处理,在不同的编译器可能会产生不同的结果,又或者如果程序调用未定义的行为,可能会成功编译,甚至一开始运行时没有错误,只会在另一个系统上,甚至是在另......
  • C++ Prime 学习
    C++利用using语句:其一:指定别名点击查看代码intp[4][4]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};for(int(*i)[4]=p;i!=p+4;i++){ for(int*j=*i;j!=*i+4;j++){ cout<<*j<<endl; }}利用using之后点击查看代码<summary>点击查看代码</su......
  • C++ 解引用与函数基础:内存地址、调用方法及声明
    C++解引用获取内存地址和值在上一页的示例中,我们使用了指针变量来获取变量的内存地址(与引用运算符&一起使用)。但是,你也可以使用指针来获取变量的值,这可以通过使用*运算符(解引用运算符)来实现:stringfood="Pizza";//变量声明string*ptr=&food;//指针声明//引用......