跳转至

内联函数

内联函数(inline)快。

函数调用的开销

在函数中调用其他函数。

每一次函数调用 都有开销。电脑CPU都要做操作。

int foo(int x)
{
    int result;
    result = x*x;
    return result;
}

函数调用开销:

  • push 函数参数
  • call 函数
  • push ebp建立函数的栈帧
  • mov ebp,esp
  • sub esp, 20 分配局部变量内容
  • 执行函数体的代码
  • mov eax,返回值
  • mov esp,ebp清除函数的栈帧
  • pop ebp
  • 执行返回指令
  • add esp,dd 取消函数参数

准备操作 执行操作 收尾操作。

内联函数与宏函数

C++为了和C语言一样快,而做的措施。

内联函数是其中的一种。

在所有的语言中,C语言是最快的。

C语言有预处理器宏。预处理函数。使得C语言运行很快。

预处理宏 一般大写。 在C语言里也把它叫函数。

#define SQUARE(X) ((X)*(X))

要多加一些小括号。避免发生错误。

和普通函数不一样。

优点:在预处理阶段进行了文本替换。而不是再写一个函数,避免函数调用的开销,所以就快。

缺点:因为是普通文本替换,容易出错。

所以C++提供更好的方法:内联函数。

内联函数和预处理宏函数速度一样。

在函数前面加inline 那就是内联函数。其他的都不用变。

C++编译的时候,检查保证没有错误,然后进行替换。也不是函数调用,没有调用的开销。

C预处理宏 没有办法进行检查,因为是在预处理阶段

C++inline函数取代C语言的宏函数。

C++ inline更安全。

内联函数不一定内联

  • 函数过大
  • 函数递归
  • 语法不对
  • 编译器没有启用内联,或没有内联功能

内联函数不能写成像普通函数那样 一个声明 一个定义。

内联函数只能有一个,写在最前面。

内联函数不需要源文件,只写在头文件里。不能分成两部分。和普通函数不一样。

类内部的内联函数

C++的功能

宏函数不可能写在类里,类的成员函数没有宏函数这样的。

类中只能写inline 内联函数。

根据需要写内联函数

比较小的函数写成内联函数,例如简单的构造函数,比较大的写了也没有用 函数里面代码很多的时候,可以写 但是写了C++编译器也不做内联。

class Point
{
    int i,j,k;
public:
    Point() : i(0),j(0),k(0){}
    Point(int ii, int jj, int kk) : i(ii),j(jj),k(kk){}
    void print(const string& msg) const
    {
        if (msg.size() != 0) cout << msg << endl;
        cout << "i = " << i << ", "
        << "j = " << j << ", "
        << "k = " << k << endl;
    }
};

在类里面定义的就是内联函数,前面不需要加inline。

一个类普通情况下:

头文件写声明,源文件写定义。

内联函数要写在头文件中。或者直接写到类的内部。

#include <stdio.h>
#include <iostream>

class Point
{
    int i,j,k;
public:
    Point() : i(0),j(0),k(0){}
    Point(int ii, int jj, int kk) : i(ii),j(jj),k(kk){}
    void print(const std::string& msg) const;
};

inline void Point::print(const std::string& msg) const
{
    if (msg.size() != 0) std::cout << msg << std::endl;
    std::cout << "i = " << i << ", "
    << "j = " << j << ", "
    << "k = " << k << std::endl;
}

带内联函数的Stash和Stack

Stash和Stack成员函数做成内联函数,加快速度,小的函数。

在头文件中,可以使用inline单独写函数实现。也可以在类里面直接写,不需要inline修饰。

构造函数中可以使用初始化列表,更加方便。因为本身就是初始化的。

Stack中的方法都是小方法,所以可以都写成内联函数,都在.h文件中。不需要源文件。

有了内联函数 Stash和Stack会更有效率。运行速度会更快。

  • 把比较小的函数变成内联函数。
  • 内联函数一定要放到头文件里

构造函数做成内联的。不能在.cpp中 应该在.h文件。

两种方法:

  1. .h头文件中

  2. .h头文件定义中 直接定义

初始化列表:

因为构造方法里面的代码都是初始化,所以可以使用初始化列表。

析构函数也做成内联函数。

// C++的Stash
class Stash
{
private:
    int size;// 每一个是多大。存字符串的话就是最多的存多少字符。
    int quantity;// 数量。一共可以保存多少个。
    int next;// 已经保存了多少个。
    unsigned char* storage;// 指针

public:
    //构造函数。对成员进行初始化 使用初始化列表
    //在类里面。现在就是内联的 不需要inline。
    Stash(int sz, int initQuantity = 0) : size(sz),quantity(0),storage(0)
    {
        inflate(initQuantity);
    }
    int add(const void* element);
    // 扩大内存
    void inflate(int increase);
    int count()
    {
        return next;
    }
    void* fetch(int index)
    {
        assert(0 <= index);
        if (index >= next) {
            return 0;
        }
        return &(storage[index * size]);
    }
    ~Stash()//析构函数 做成内联的
    {
        if (storage != 0) {
            delete [] storage;
        }
    }
};

在头文件中。比较小的函数做成内联的。

add和inflate函数比较大,就不做内联的。

count和fetch比较小,做成内联的。

inline int Stash::count()
{
    return next;
}

inline void* Stash::fetch(int index)
{
    assert(0 <= index);//要包含C++头文件#include <cassert>
    if (index >= next) {
        return 0;
    }
    return &(storage[index * size]);
}

内联函数一定要在.h文件里。

也可以写到类的内部。

内联函数编程指南

内联函数写法不统一,不同的人写的不一样,为了统一做的编程指南。

写成这样的比较好。

class Rectangle
{
    int width, height;
public:
    //构造函数
    Rectangle(int w = 0, int h = 0);
    int getWidth() const;
    void setWidth(int w);
    int getHeight() const;
    void setHeight(int h);
};

inline Rectangle::Rectangle(int w, int h) : width(w), height(h) {}
inline int Rectangle::getWidth() const
{
    return width;
}
inline void Rectangle::setWidth(int w)
{
    width = w;
}
inline int Rectangle::getHeight() const
{
    return height;
}
inline void Rectangle::setHeight(int h)
{
    height = h;
}

运行代码 测试是否正确。

//测试
void test()
{
    Rectangle r(19, 47);
    int iHeight = r.getHeight();
    cout << iHeight << endl;
    r.setWidth(100);
    r.setHeight(r.getWidth());
    cout << r.getWidth() << endl
    << r.getHeight() << endl;
}

内联函数写在类的定义外面。

优点:

想要内联的时候就加上inline 不想的时候就把inline去掉。方便。

内联如果写在类的里面,不想做成内联了 还得从里面复制出来。麻烦。所以写在外面。