zoukankan      html  css  js  c++  java
  • C++之内联函数

      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
    ");
    }
    void main()
    {
        ifstream nofile;
        nofile.open("nofile.xxx", ios::in);
        allegefile(nofile);
        return;
    }

    #define assert(_Expression) (void)( (!!(_Expression)) || (_wassert(_CRT_WIDE(#_Expression), _CRT_WIDE(__FILE__), __LINE__), 0) )
    assert()宏中包含__FILE__和__LINE__
  • 相关阅读:
    我觉得总结的不错的entityFramework
    vs2013引入com组件后,发布时如何提取出dll文件
    win10创建扩展分区
    web.config配置
    mysql时间增加一年
    json介绍
    phpcms列表分页ajax加载更多
    phpcms批量更新内容页只更新一点就返回问题
    phpcms不能批量更新栏目页和内容页
    iis设置默认文档,提示web.config配置xml格式不正确
  • 原文地址:https://www.cnblogs.com/xiaobingqianrui/p/8796234.html
Copyright © 2011-2022 走看看