C++之内联函数

C++继承C的一个重要特性是效率,在C中保护效率的一个方法是使用宏(macro),宏的实现是使用预处理器而不是编译器,预处理器直接用宏代码替换宏调用,所以就没有了参数压栈、生成汇编语言的CALL、返回

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

全栈程序员社区此处内容已经被作者隐藏,请输入验证码查看内容
验证码:
请关注本站微信公众号,回复“验证码”,获取验证码。在微信里搜索“全栈程序员社区”或者“www_javaforall_cn”或者微信扫描右侧二维码都可以关注本站微信公众号。

  C++继承C的一个重要特性是效率,在C中保护效率的一个方法是使用宏(macro),宏的实现是使用预处理器而不是编译器,预处理器直接用宏代码替换宏调用,所以就没有了参数压栈、生成汇编语言的CALL、返回参数、执行汇编语言的RETURN的时间花费,所有的工作由预处理器完成,因此不用花费什么就具有了程序调用的便利和可读性。

  C++中使用预处理器宏存在两个问题,一是不安全性,二是C++特有的,预处理器不容许存取私有数据,这意味着预处理器在用作成员函数时变得非常无用。

  为了既保持预处理器宏的效率又增加安全性,而且还能像一般的成员函数一样可以在类里访问自如,C++使用了内联函数。

内联函数与编译器

  内联函数使用inline关键字定义,为了使之有效,必须使函数体和声明结合在一起,否则,编译器将它作为普通函数对待

  一般应该把内联定义在头文件中,当编译器看到这个定义时,它把函数类型(函数名+返回值)和函数体放到符号表里,当使用函数时,编译器检查以确保调用和返回是否正确,然后将函数调用替换为函数体,因而消除了开销,内联代码的确占用空间,但假如函数较小,这实际比为了一个普通函数调用而产生的代码(参数压栈和执行CALL)占用的空间少。

1. 局限性

  编译器在以下两种情况下不能处理内联:

  (1) 函数体很大或很复杂,任何种类的循环都被认为太复杂,编译器遇到这种情况都会放弃内联方式,因为这时内联将可能不为我们提供任何效率

  (2) 假如我们要显示或隐含地取函数地址,编译器也不能执行内联,因为这时编译器必须为函数代码分配内存从而为我们产生一个函数的地址。

  我们必须理解内联仅仅是编译器的一个建议,编译器不强迫内联任何代码,一个好的编译器将会内联小的,简单的函数,同时明智的忽略那些太负责的内联

2. 赋值顺序

class forward
{
public:
    forward():i(0){}

    int f() const {return g() + 1;} // 注意
    int g() const {return i;}

private:
    int i;
};
void main()
{
    forward F;
    F.f();
    return;
}

  观察上面的代码,虽然函数g()还没有定义,但在函数f()里对函数g()进行了调用,编译器会不会报错呢?

  事实上这是可行的,因为语言定义规定非内联函数直到类声明结束才赋值。

假如一个内联函数对于一个还没有在内里面声明的函数进行向前引用,编译器就不会把它当做内联函数处理!

错误检查示例

inline void allege_error(int nVal, char *cMsg)
{
    if (!nVal)
    {
        fprintf(stderr, cMsg);    
    }
#ifdef NDEBUG
        exit(1);
#endif
    
}
#define allege(expr, msg)\
{\
    allege_error((expr ? 1:0), msg);\
    assert(expr);\
}

#define allegemem(expr)\
{\
    allege(expr, "out of memory");\
}

#define allegefile(expr)\
{\
    allege(expr, "could not open file\r\n");\
}
void main()
{
    ifstream nofile;
    nofile.open("nofile.xxx", ios::in);
    allegefile(nofile);
    return;
}

C++之内联函数

#define assert(_Expression) (void)( (!!(_Expression)) || (_wassert(_CRT_WIDE(#_Expression), _CRT_WIDE(__FILE__), __LINE__), 0) )

assert()宏中包含__FILE__和__LINE__

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/120176.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • SQL 清空表数据的方法

    SQL 清空表数据的方法truncatetabletablenamedeletefromtablenamedelete方法最大的问题,当有标志字段时就有问题一般建議盡可能使用delete去刪除表的字段,它具有選擇性刪除的作用,所以常常deletefromtablenamewhere條件delete和truncate作用其實是一樣的,隻是truncate后面不跟where條件句,它的作用是刪除表中所有的行(記錄)兩者最大的區別就是delete是寫日誌文件的,而truncate則不寫日誌直接刪除

    2022年6月5日
    58
  • QuoteName\生成Sql语句

    QuoteName\生成Sql语句ifexists(selectnamefromtempdb.dbo.sysobjectswhereid=object_id(N’tempdb.dbo.#tempWorkDate’)andtype=’u’)droptable#tempWorkDateCREATETABLE[#tempWorkDate]([WorkDate][varc…

    2022年7月25日
    7
  • js生成二维码_js生成二维码并保存

    js生成二维码_js生成二维码并保存js生成二维码一、一个简单的示例前段时间项目中需要开发扫描二维码查看信息的功能,在网上查了一些资料,把用过的方法进行总结需要导入一个qrcode的js插件。一、一个简单的示例如下:(仅供参考)<%–CreatedbyIntelliJIDEA.User:ASUSauthor:xumzDate:2021/2/27Time:10:33搬运请备注TochangethistemplateuseFile|Settings|Fil

    2022年10月18日
    2
  • C++学生选课系统 【含 代码】

    C++学生选课系统 【含 代码】1.系统分析本系统的用户分为普通用户和管理员两类,其中普通用户包括教师和学生。普通用户只能对自己的信息进行查询与修改,管理员则拥有所有功能权限。1.1模块划分学生选课系统,在登录模块之后,根据系统用户的身份不同划分为三个模块,即:学生模块、教师模块和管理员模块。1.2功能模块描述(1)登录模块登录模块用于用户身份选择与用户登录,完成基本的验证。根据所填信息进行…

    2022年10月15日
    3
  • 关于VUE双向绑定失效的问题「建议收藏」

    关于VUE双向绑定失效的问题「建议收藏」双向绑定失效的原因有很多。lz就说最近遇到的。是的,单价下的那个输入框我用了双向绑定(比如叫price,比如100)。然后ipnut键入中文时,(即使我做了输入验证)。回车时虽然框中不会保留中文,但事实上VUE的双向绑定已经失效了。不管你后面输入什么,绑定的price保存的值只会是中文前的那个值(100)。这样就导致表面好像没事,但是当你提交时就数据不对了。还有

    2022年9月14日
    3
  • rabbitmq集群搭建「建议收藏」

    rabbitmq集群搭建「建议收藏」一、基础安装前提:三个节点都主机映射,关防火墙网络,配好yum(后边出错,主机名和映射要对应)1.安装(三个节点)2.mq1启动rabbitmq服务查看状态3.配置界面访问4.使用界面查看(端口15672,默认帐户和密码guest)二、配置rabbitmq集群服务1.先构建erlang集群①复制cookie认证②配置节点加入集群(顺序很重要,解决报错看)123的顺序停止321的顺序启动rabbitmq服务

    2025年10月25日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号