C++之inline的使用

51cto/2023/9/30 6:54:57

inline的使用

  • 一.普通函数inline
    • 1.关键字inline 必须与函数定义体放在一起才能使函数成为内联,仅将inline 放在函数声明前面不起任何作用。
    • 2.把内联函数的定义放在头文件中
  • 二.类的成员函数inline
    • 类的构造函数,析构函数的inline

  • 首先,明白一点:不是你指定函数inline就inline,关键看编译器是否认可。我们使用inline关键字指定inline函数仅仅是向编译器提的请求,编译器完全可以忽略这个请求
  • 其次,inline机制一般用于规模较小(可理解为行数少)、流程直接(可理解为没有for循环)、频繁调用的函数。

一.普通函数inline

1.关键字inline 必须与函数定义体放在一起才能使函数成为内联,仅将inline 放在函数声明前面不起任何作用。

如下面的函数Foo 不能成为内联函数[1]

inline void Foo(int x, int y); // 在函数声明前加inline,此时不能成为inline函数void Foo(int x, int y)
{
}

而下面的函数Foo2 则成为内联函数:

inline void Foo2(int x, int y) // 在函数的定义处使用inline关键字,是inline函数
{
}

所以说,inline 是一种 “用于实现的关键字” ,而不是一种“用于声明的关键字”。一般地,用户可以阅读函数的声明,但是看不到函数的定义。尽管在大多数教科书中内联函数的声明、定义体前面都加了inline 关键字,但我认为inline 不应该出现在函数的声明中。这个细节虽然不会影响函数的功能,但是体现了高质量C++/C 程序设计风格的一个基本原则:声明与定义不可混为一谈,用户没有必要、也不应该知道函数是否需要内联。

[1] : 参考:[内联函数 —— C 中关键字 inline 用法解析]{https://blog.csdn.net/zqixiao_09/article/details/50877383}

2.把内联函数的定义放在头文件中

由于inline函数需要展开的缘故,所有调用inline函数的源文件必须包含inline函数的定义,因为仅仅有函数的声明无法做到函数的展开。这可以当成是inline函数和其他函数不同的一个地方:即inline函数可以多重定义

为了避免一个inline函数在多个源文件(.cpp文件)中出现,我们应该把inline函数的定义放在一个头文件(.h文件)中,所有调用inline函数的源文件(.cpp文件)包含此头文件即可
如:
在test_inline.h中定义一个inline函数:

#ifndef _TEST_INLINE_
#define _TEST_INLINE_#include <iostream>inline void print()
{std::cout << "我是inline函数" << std::endl;
}#endif

其他源文件包含test_inline.h即可。

二.类的成员函数inline

请看下面的一个类,摘抄至C++ Primer第5版:

//头文件Test_inline.h中
class Screen
{
public:typedef std::string::size_type pos;Screen() = default;Screen(pos ht, pos wd, char c) : height(ht), width(wd), contents(ht*wd, c){}char get() const//1.在类内定义函数,默认为隐式inline函数{return contents[cursor];}inline char get(pos r, pos c) const;//2.在声明处,显式内联Screen& move(pos r, pos c);//3.成员函数可以在类外定义处内联private:pos cursor = 0;pos height = 0, width = 0;std::string contents;
};//2.在声明处,显式内联
char Screen::get(pos r, pos c) const
{pos row = r * width;return contents[row + c];
}//3.成员函数可以在类外定义处内联
inline Screen& Screen::move(pos r, pos c)
{pos row = r * width;cursor = row + c;return *this;
}

不难发现类的成员函数为inline的3种情形:

  1. 在类的内部直接定义函数,这是隐式的inline函数,如char get() const;
  2. 在类的声明处用inline关键字,这是显示化成员函数,如inline char get(pos r, pos c) const;
  3. 在类外部定义处用inline关键字,如inline Screen& Screen::move(pos r, pos c){}

  • 注意第2条和普通函数的内联的区别:类的成员函数声明可以成为内联函数。
  • 此外,在定义和声明处都写上inline关键也是可以的,不过最好还是在定义处说明inline,就像上述第 3条一样。
  • 成员函数inline的定义也要和类的定义放在同一头文件中,原因和普通函数inline一样。

类的构造函数,析构函数的inline

看C++编程思想上的一个实例:
在这里插入图片描述

在类withMembers里,内联的构造函数和析构函数看起来似乎很直接和简单,但其实很复杂,因为成员对象Q、P和S的构造函数和析构函数被自动调用。

[2]所以说,表面上类的构造函数和析构函数使用内联更有效。实际上,要当心构造函数和析构函数可能会隐藏一些行为:“偷偷地”执行了基类或成员对象的构造函数和析构函数,所以不要随便地将构造函数和析构函数的定义体放在类声明中

[2]:参考:[https://www.cnblogs.com/fnlingnzb-learner/p/6423917.html](https://www.cnblogs.com/fnlingnzb-learner/p/6423917.html)

以上就是全部的内容,如果有疑问,欢迎评论区下方留言;本人水平有限 ,如有错误,也欢迎在评论区下方批评指正。若是喜欢本文,就帮忙点赞吧!


http://www.ngui.cc/51cto/show-221.html

相关文章

自我介绍以及编程学习目标

大家好&#xff0c;我叫陈建旭&#xff0c;我来自福建省福州市。 目前就读于厦门理工学院。 本人擅长研究数学&#xff0c;包括分析学与代数学&#xff0c;现在水平有限还在不断提升&#xff0c;目前希望在计算机知识方面得到提高。 我对编程的目标是&#xff1a;熟练掌握c …

前端构建工具GruntGulpwebpack笔记

Grunt项目构建 概述 项目构建就是并编译, 合并, 压缩项目中的JS, SASS, LESS文件; 压缩HTML资源文件; JS语法检查 Grunt就是用来进行自动化项目构建的, Grunt由一组插件组成, 围绕Grunt工作实现自动化, 常见的功能有 合并JS/CSS压缩JS/CSSJS语法检查LESS/SESS的预编译 目录…

【疑问解答】关于VLAN技术您了解多少?

当以太网中主机数量过多时会导致冲突严重、广播泛滥、性能明显下降甚至造成网络无法使用等问题&#xff0c;虽说可以通过交换机实现LAN互连解决冲突严重的问题&#xff0c;但是仍然无法实现广播报文隔离&#xff0c;提高网络质量。为解决这一些列问题&#xff0c;VLAN技术应运而…

Android 开发岗往年至今年高频面试题整(内含参考答案)

2 ) 动态注册:动态注册的广播接收者只有执行了 registerReceiver(receiver, filter)才会开始监听 广播消息&#xff0c;并对广播消息作为相应的处理。 IntentFilter fiter new IntentFilter(“com.smilexie.test.intent.mybroadcastreceiver”); MyBroadcastReceiver recei…

Vue2/3入门笔记

Vue包括 Vue: 基础用户界面Vue-cli: 脚手架, 用于工程化开发vue-router: 前端路由vuex: 数据保管服务 Vue2核心 Vue是一套用于构建用户界面(数据->页面)的渐进式(自底向上)JavaScript框架 采用组件化的模式构建: 每一个组件都是一个.vue文件, 文件包含了组件需要的JS/CS…

剑指offer-树2m栈队列2e1m1h-10

目录[JZ86 (m)在二叉树中找到两个节点的最近公共祖先][1][JZ68 (m)二叉搜索树的最近公共祖先][2][JZ9 (e)用两个栈实现队列][3][JZ30 (e)包含min函数的栈][4][JZ31 (m)栈的压入、弹出序列][5][JZ73 (h)翻转单词序列][6]今天学到的知识JZ86 (m)在二叉树中找到两个节点的最近公共…

Atml_at91sam9260ek

1. AT91SAM9260 AT91SAM9260 CPU从属于ARMARCH5, vxWorks6.6支持的ARM architectures: 支持的pcocessors: VxWorks6.7 在vx6.6的基础上又增加了对processors:ARM7TDMI的支持和以下CPU变种的支持: 进行ARM BSP, estimation时需要关注arch的支持情况,目前vxWorks版本已经支…

Vue3TypeScript踩坑汇总

安装环境 1.node版本12以上 创建项目 npm init vitejs/app 项目名1、配置路由 router-index.ts npm install vue-router4 --saveimport { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router"; const routes: Array<RouteRecordRaw>…

【Android】getDimension相关记录

1&#xff0c;概述 一直以为调用context.getResources().getDimension(R.dimen.xxx)只会获取dimens.xml 中写入的值&#xff0c;但其实已经转换为屏幕desity对应的像素值了&#xff1b; 2&#xff0c;源码 public float getDimension(DimenRes int id) throws NotFoundExce…

Java面试---Day2

Java面试—Day2 星光不问赶路人&#xff0c;时间不负有心人 文章目录Java面试---Day21、泛型中的extends和super的区别2、进程和线程的区别3、final、finally、finalize的区别4、序列化的方式5、Serializable 和 Parcelable 的区别6、静态属性和静态方法是否可以被继承&#xf…