Effective-C++学习记录——条款2-3

条款二——使用const,enums,inline 替换#define

变量使用 const,enums 替换define
函数使用 inline 替换define

define 会在预处理阶段进行替换,程序的可读性会很差

思维导图
在这里插入图片描述

const替换define

特殊情况一

当需要将指针放到头文件中方便其他文件使用,必要时将指针声明成常量指针+指针常量的形式: const char* const sp = "adsf",这种情况下可以使用const string sp("asdf") 进行替换

特殊情况二

需要在类内使用一个常量定义数组时,可能需要一个class专属的常量进行定义
方法一: 可以使用define在类中定义常量使用,并在使用完之后立即#undef,就可以满足在一个类中定义常量的需求(默认使用#define是全局可见的,所以需要使用#undef来限制作用域)
方法二
需要先明确什么类型的变量能定义数组大小——static const 变量
全局中定义一个const变量也是可以定义数组大小——全局变量存储在静态区中,相当于默认就是静态变量

class A
{
public:
    static const int NUM = 5;
    int _nums[NUM];
};
 //const int A::NUM = 5;

同时可以使用enum代替define达到既在类内,又能定义数组的目的

    enum { NUM = 5 };
    int _nums[NUM];

使用inline替换define函数

先看一个经典案例
在这里插入图片描述
这中代码看起来就很坑,而且很不好调试
可以使用inline进行替换,而且inline拥有函数作用域的特性,同时也一定程度上拥有define在预处理时被替换的特性(inline更像是一种建议,建议编译器替换,对于较长的代码是不会进行替换的)

template<class T>
inline void fun(T a, T b)
{
    f((a) > (b) ? (a) : (b));
}

写成这个样子,更安全

条款三——尽量使用const

思维导图

在这里插入图片描述

int* + const

#include<iostream>
using namespace std;

int main()
{
    // const + int* 的基本使用
    int a = 10;
    const int* pa = &a;// 常量指针常量不可改——不能*pa = 20;
    int const* pb = &a;// 同上,只有写法不同
    int* const pc = &a;// 指针常量指向不可改—— 不能 pb = pa
    const int* const pd = &a;// 常量指针+指针常量——既不能 pd = pa;又不能*pd = *pa

    return 0;
}

iterator,const_iterator,const iterator的区别

iterator——int*
const iterator ——int* const 指针常量,指向不可改
const_iterator —— const int* 常量指针,内部变量不能改变

降低用户使用时带来的错误

需要修改内部const成员

当需要使用const 实例修改内部变量时
在这里插入图片描述

使用mutable关键字来修饰,用来释放non-static的const 约束——可以让他再const实例中进行修改
在这里插入图片描述

class A
{
public:
    void fun(int a) const
    {
        _a = a;
    }
    mutable int _a;
};
int main()
{
    const A cona;
    cona.fun(10);
    cout << cona._a << endl;
    cona.fun(20);
    cout << cona._a << endl;

    return 0;
}

const和non-const成员函数避免重复

const 和non-const成员函数一般实现都是一样的,只有调用函数的实例的属性不一样,作为程序员尽量避免写出这种重复的代码

class A
{
public:
    const int& operator[](const int p) const
    {
        return _nums[p];
    }
    int& operator[](const int p)
    {
        return _nums[p];
    }
    int _nums[100];
};

使用const函数调用non-const函数

class A
{
public:
    const int& operator[](const int p) const
    {
        return _nums[p];
    }
    int& operator[](const int p)
    {
        // const_cast<T> , T 只能是引用,指针,指向成员类型的指针
        return const_cast<int&>(static_cast<const A&>(*this)[p]);
    }
    int _nums[100];
};

static_cast —— 普通的类型转换
const_cast —— 去除const属性
static_cast<const A&> —— 将*this 从原始类型 A& 转换为cosnt A&
const_cast<int&> —— 完成const 向 non-const 安全转换
不能再non-const内部直接调用operator[],这样会无限递归下去,也就是自己调用自己
不能使用const 调用 non-const (可能在调用non-const函数的内部对数据进行改变,很危险)

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值