const用法以及一些思考

const用法

背景

在c++中不管是定义常量,还是在函数的参数列表中都经常会使用到const,虽然知道const修饰变量后表示不可以修改,但是经常还是会在具体的使用中出错,所以想要彻底的弄懂它。

关键知识点

介绍

**const是一个关键字,用于声明一个变量为常量,这意味着一旦被赋值后,其值就不能被改变。在C++中,const**可以用来声明常量变量、常量指针、指向常量的指针等,以确保它们指向的值或它们本身在程序运行过程中不被修改。

面临的问题

在软件开发的早期阶段,程序员经常面临因变量值被意外修改而导致的bug。为了解决这个问题,**const**关键字被引入,以便开发者可以明确地标记某些变量是不应该被修改的,从而提高代码的稳定性和可读性。

const修饰指针

  1. 常量指针:const 关键字位于指针类型之前,表示指针指向的内容不能被修改,但指针本身可以指向其他对象。

示例:

int a = 10;
const int* p1 = &a; // p1 指向 a,但不能修改 *p1 的值
*p1 = 20; // 错误,无法修改 *p1 的值
p1 = &b; // 可以修改 p1 指向的对象

  1. 指针常量:const 关键字位于指针类型之后,表示指针本身不能被修改,但指针指向的内容可以被修改。

示例:

C++

int a = 10, b = 20;
int* const p2 = &a; // p2 指向 a,且不能修改 p2
*p2 = 20; // 可以修改 *p2 的值
p2 = &b; // 错误,无法修改 p2 指向的对象

  1. 常量指针常量:const 关键字位于指针类型两侧,表示指针指向的内容和指针本身都不能被修改。

示例:

C++

int a = 10;
const int* const p3 = &a; // p3 指向 a,且不能修改 *p3 和 p3
*p3 = 20; // 错误,无法修改 *p3 的值
p3 = &b; // 错误,无法修改 p3 指向的对象

总结

const 用于修饰指针时,可以根据其位置来判断其作用:

  • 位于指针类型之前:常量指针,指向的内容不可修改
  • 位于指针类型之后:指针常量,指针本身不可修改
  • 位于指针类型两侧:常量指针常量,指针指向的内容和指针本身都不可修改

const 修饰方法

在 C++ 中,const 关键字可以用于修饰类的方法。这种方法被称为常量成员函数。常量成员函数不会修改对象的状态,也就是说,它不能修改任何成员变量(除非它们是用 mutable 关键字声明的)和调用非 const 的成员函数。

声明及定义

class MyClass {
public:
    // 常量成员函数声明
    int getValue() const;

private:
    int value;
};

// 常量成员函数定义
int MyClass::getValue() const {
    return value;
}

类成员常量

class MyClass {
public:
    const int myConst;

    MyClass(int val) : myConst(val) {
        // myConst must be initialized in the initializer list.
    }
};

c++中常量该怎么定义?

在C++中,常量可以通过**const**关键字声明和定义,以确保其值在程序执行期间不被修改。下面是一些声明和定义常量的基本方法:

1. 基本类型的常量

对于基本数据类型(如整数、浮点数等),可以直接在变量声明时使用**const**关键字来创建常量。

const int MAX_USERS = 100;
const double PI = 3.14159;

2. 指针常量

对于指针,**const的使用稍微复杂一些,因为它可以用来声明指向常量的指针或者常量指针,这取决于const**关键字的位置。

  • 指向常量的指针(指针可以改变,指向的值不能改变):
const int* ptrToConst;
  • 常量指针(指针不能改变,指向的值可以改变):
int* const constPtr;
  • 指向常量的常量指针(指针和指向的值都不能改变):
const int* const constPtrToConst;

3. 类成员常量

在类中,可以使用**const**来声明常量成员变量。这通常在类的构造函数初始化列表中赋值。

class MyClass {
public:
    const int myConst;

    MyClass(int val) : myConst(val) {
        // myConst must be initialized in the initializer list.
    }
};

4. 枚举常量

枚举(Enumeration)是一种定义在类中的常量集合,它是固定的,不能改变。

enum class Colors {
    Red,
    Green,
    Blue
};

5. constexpr 常量

C++11引入了**constexpr**关键字,用于编译时常量的声明,这可以用于变量、函数和类构造函数,以提高程序的效率。

constexpr int getArraySize() {
    return 32;
}

constexpr int arraySize = getArraySize();
int myArray[arraySize];

使用**constexpr**声明的函数必须满足特定条件,使得它们在编译时就能被求值。

注意事项

  • 使用**const**声明的常量必须在声明时初始化。
  • **constconstexpr的主要区别在于constexpr**用于那些必须在编译时就确定值的表达式。
  • 类中的**const成员函数表示该函数不会修改任何成员变量(除了那些被声明为mutable**的成员变量)。

通过这些方法,你可以在C++中有效地声明和定义常量,以提高代码的可读性和维护性。

constexpr和const有什么区别?

**constexprconst**在C++中都用于声明常量,但它们的用途和含义有所不同。下面是它们之间的主要区别:

1. 编译时常量 vs 运行时常量

  • const:用于声明一个值不可变的常量。**const**可以在编译时或运行时初始化,这意味着它的值可以在编译时已知,也可以在运行时才确定。
  • constexpr:引入于C++11,用于声明一个必须在编译时就确定其值的表达式。这使得**constexpr**非常适合定义编译时常量和函数,可以在编译时进行计算和检查。

2. 用途

  • const:广泛用于声明各种类型的常量,包括对象、基本数据类型、指针等,其值在声明后不可更改。
  • constexpr:用于优化程序,通过在编译时计算表达式值来减少运行时的计算量。**constexpr**适用于函数、对象构造函数以及简单的数值计算。

3. 函数和构造函数

  • const:不能用于函数或构造函数的声明。
  • constexpr:可以用于函数和构造函数,要求函数体中的操作和返回值都必须是编译时可确定的。这允许在编译时进行函数调用和对象创建。

4. 存储位置

  • const:可以用于静态存储期(如全局常量)和自动存储期(如局部常量)的对象。它不强制要求变量必须在编译时有确定的值。
  • constexpr:虽然**constexpr**变量通常存储在程序的只读存储段中,但关键是它们必须在编译时就能被求值。

5. 类型限制

  • const:几乎可以用于任何类型的变量,不要求变量类型在编译时可知。
  • constexpr:要求变量或函数的类型必须是字面类型(Literal Type),这意味着类型必须具有至少一个**constexpr**构造函数,从而能在编译时被构造或计算。

示例

  • const示例
const int maxUsers = 100; // 运行时常量
  • constexpr示例
constexpr int getMaxUsers() {
    return 100; // 编译时常量
}

总结

**constconstexpr都是用于声明常量的关键字,但constexpr的引入是为了在编译时进行更多的计算,从而优化程序性能。constexpr适用于那些可以在编译时完全确定的场景,而const**更加通用,适用于运行时和编译时的常量声明。

  • 40
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值