inline mutable default delete

介绍

inline(内联函数)

inline关键字用于函数定义,是一个编译器优化建议,用于提高函数调用的效率。

inline int add(int a, int b) {  
    return a + b;  
}

特点:

  • 建议编译器在调用处直接展开函数,避免函数调用开销
  • 编译器可以自行决定是否真正内联
  • 适用于短小、频繁调用的函数
  • 可以减少函数调用的栈开销

mutable(可变成员)

mutable用于修饰类的成员变量,允许在const成员函数中修改该成员变量。

class Cache {  
private:  
    mutable int access_count = 0;  // 可以在const成员函数中被修改  
public:  
    int getData() const {  
        access_count++;  // 即使在const函数中也可以修改  
        return 42;  
    }  
};

特点:

  • 允许在const成员函数中修改特定成员变量
  • 常用于缓存、计数等辅助性成员
  • 不影响对象的整体const语义

default(默认函数)

default用于显式地声明编译器默认生成的特殊成员函数。

class MyClass {  
public:  
    MyClass() = default;  // 显式使用编译器生成的默认构造函数  
    MyClass(const MyClass&) = default;  // 默认拷贝构造  
    MyClass& operator=(MyClass&&) = default;  // 默认移动赋值  
};

特点:

  • 明确告诉编译器使用默认实现
  • 可以提高代码可读性
  • 在某些情况下可以避免编译器阻止特殊成员函数的生成

delete(删除函数)

delete用于禁止使用特定的函数或运算符。

class Singleton {  
public:  
    Singleton(const Singleton&) = delete;  // 禁止拷贝构造  
    Singleton& operator=(const Singleton&) = delete;  // 禁止拷贝赋值  
    static Singleton& getInstance() {  
        static Singleton instance;  
        return instance;  
    }  
private:  
    Singleton() {}  // 私有构造函数  
};  

class NonHeap {  
public:  
    void* operator new(size_t) = delete;  // 禁止在堆上分配  
    void* operator new[](size_t) = delete;  
}; 

void processOnly(int x) { /* 处理整数 */ }  
void processOnly(double) = delete;  // 禁止double重载

特点:

  • 明确禁止某些函数的使用
  • 可以阻止不期望的类型转换和函数调用
  • 在编译期就能检查和阻止不正确的使用

综合示例

class SmartCache {  
private:  
    mutable int access_count = 0;  
    int* data = nullptr;  

public:  
    SmartCache() = default;  // 默认构造  
    SmartCache(const SmartCache&) = delete;  // 禁止拷贝  
    SmartCache& operator=(const SmartCache&) = delete;  

    inline int getData() const {  
        access_count++;  // mutable允许在const函数中修改  
        return data ? *data : 0;  
    }  
};

用法

inline

inline关键字作用:

在函数定义中函数返回类型前加上关键字inline就可以把函数指定为内联函数

内联函数的作用,普通函数在调用时需要给函数分配栈空间以供函数执行,压栈等操作会影响成员运行效率,于是C++提供了内联函数将函数体放到需要调用函数的地方,用空间换效率。

简单来说:普通函数调用需要分配新的栈空间,然后执行压栈等操作,而内联函数调用可以继续在当前的函数栈帧里执行,提高了运行效率,典型的以空间换时间

总结:使用 inline 关键字就是一种提高效率,但加大编译后文件大小的方式,现在随着硬件性能的提高,inline关键字用的越来越少了

inline关键字的注意事项:

(1) inline关键字只是一个建议,开发者建议编译器将成员函数当做内联函数,一般适合搞内联的情况编译器都会采纳建议

eg: 如果一个函数所需要分配的栈非常大,例如代码量很大的函数,或者是递归函数,他们需要分配的栈空间都很大,这个时候编译器就不会把它当作内联函数;

(2) 关键字 inline 必须与函数定义放在一起才能使函数成为内联,仅仅将inline放在函数声明前不起任何作用;简单来说:就是inline关键字必须与函数定义放在一起,函数声明加不加inline无所谓;

(3) 直接在类内部实现的函数,相当于函数默认加了inline关键字

inline相关代码:

#include <iostream>

class Test
{
public:
    Test() {}
    ~Test() {}
    inline void func1();
    inline void func2();
    void func3();
    void func4()
    {
        std::cout << "call func4()" << std::endl;
    }
};

inline void Test::func1()
{
    std::cout << "call func1()" << std::endl;
}

void Test::func2()
{
    std::cout << "call func2()" << std::endl;
}

inline void Test::func3()
{
    std::cout << "call func3()" << std::endl;
}

int main()
{
    Test t1;
    t1.func1();   // 函数声明和定义都加inline关键字,建议成内联函数
    t1.func2();   // 函数声明加inline,函数定义不加,不是内联函数
    t1.func3();   // 函数声明不加,函数定义加inline关键字,建议成内联函数
    t1.func4();   // 类内实现函数,建议成内联函数

    // 总结:
    // 1. 关键字 inline 必须与函数定义放在一起才能使函数成为内联,
    // 2. 直接在类内部实现的函数,默认相当于加了inline关键字
    return 0;
}

mutable 关键字

mutable关键字的作用:

mutable意为可变的,与const相对,被mutable修饰的成员变量,永远处于可变的状态;

mutable关键字修饰的变量在常函数中,该变量也可以被更改 (常函数中原本是不允许修改成员变量的)这个关键字在现代 C++中使用情况并不多,只有在统计函数调用次数这类情况下才推荐使用

mutable 关键字的注意事项:

(1) mutable不能修饰静态成员变量和常成员变量

mutable相关代码

#include <iostream>

class Test
{
public:
    Test() {}
    ~Test(){}

    void output() const   // mutable关键字修饰的成员变量 可以在常函数里修改
    {
        ++outputCallCount;
        std::cout << "hello world" << std::endl;
    }


    // C++11新特性,直接初始化成员变量 <=> 代替 定义成员 + 构造函数初始化
    mutable unsigned outputCallCount = 0;   // mutable关键字可以修饰普通成员变量
    //mutable static int i = 0;               // mutable关键字不能修饰静态成员变量
    //mutable const int j = 0;                // mutable关键字不能修饰常成员变量

};


int main()
{
    Test t1;
    t1.output();
    t1.output();
    t1.output();

    std::cout << t1.outputCallCount << std::endl;

    return 0;
}

default 关键字

default 关键字的作用:

(1) 便于书写默认构造函数,默认拷贝构造函数,默认的赋值运算符重载函数,默认的析构函数,default关键字表示使用的是系统默认提供的代码,这样可以使代码更加直观,方便;

defalut 关键字注意事项:

(1) 现代 C++中,哪怕没有构造函数,也推荐将构造函数用default关键字标记,可以让代码看起来更加直观,方便

Comment

(2) 使用default关键字 语法层面就是函数声明 return_type fucntion_name (para list) = default

default相关代码:

#include <iostream>

class Test
{
public:
    Test() = default;             // 默认构造函数  
    ~Test() = default;            // 默认析构函数
    Test(const Test& test) = default;   // 默认复制构造函数
    Test& operator=(const Test& test) = default;   // 赋值运算符重载函数   赋值运算符
};

int main()
{
    return 0;
}

delete 关键字

delete 关键字的作用:

(1) C++会为一个类生成默认构造函数,默认析构函数,默认复制构造函数,默认重载赋值运算符,在很多情况下,我们并不希望这些默认的函数被生成,为了解决这个问题,在 C++11 以前,只能有将此函数声明为私有函数或是将函数只声明不定义两种方式。于是在C++11中提供了 delete 关键字,只要在函数最后加上“=delete”就可以明确告诉编译期不要默认生成该函数

总结:delete关键字还是推荐使用的,在现代 C++代码中,如果不希望一些函数默认生 成,就用 delete 表示,这个功能还是很有用的,比如在单例模式中

delete 关键字注意事项:

(1) delete一般不会用使用在析构函数

delete相关代码

#include <iostream>

class Test
{
public:
    Test() = delete;                                // 默认构造函数  
    ~Test() = delete;                               // 默认析构函数
    Test(const Test& test) = delete;                // 默认复制构造函数
    Test& operator=(const Test& test) = delete;     // 默认重载运算符
};

int main()
{
    return 0;
}