c++ 常量 常指针 常函数 常对象

1. 常量

在C++中,常量(Constants)是指在程序执行期间不会改变其值的变量。常量是一种值被设置后不能被修改的标识符。使用关键字 const 可以声明常量,并将其与一个特定的值绑定。

1.1 常量的使用场景

  1. 防止数据被修改:通过将变量声明为常量,可以确保其值在初始化后不会被修改,从而增加程序的可靠性和安全性。特别是在函数中传递参数时,将参数声明为常量可以避免对参数值的意外修改。
void processData(const int value) {
    // value = 10;  // 错误,常量不可修改
    // 处理数据
}
  1. 提高程序可读性:通过将常量定义为具有描述性的名称,可以提高程序的可读性和可维护性。这样,在代码中使用常量的地方,可以直接使用具有描述性的名称,而无需记住具体的数值或字符串。
const int MAX_COUNT = 100;
for (int i = 0; i < MAX_COUNT; ++i) {
    // 循环操作
}
  1. 避免硬编码:常量的使用可以避免在代码中直接使用数值或字符串,从而减少硬编码。这样,如果需要修改常量的值,只需要修改常量的定义,而无需在代码中逐个修改。
const float PI = 3.14159;
float radius = 5.0;
float area = PI * radius * radius;
  1. 优化代码:在某些情况下,编译器可以利用常量的值进行优化,例如在编译时进行常量折叠(Constant Folding)和循环展开(Loop Unrolling),从而提高程序的执行效率。
const int LOOP_COUNT = 100;
for (int i = 0; i < LOOP_COUNT; ++i) {
    // 循环操作
}

1.2 使用常量时要遵循规则:

  1. 常量必须在声明时进行初始化,并且初始化后不能再修改其值。
  2. 常量命名通常使用全大写形式,并采用下划线分隔单词(例如MAX_SIZE)。
  3. 使用常量时应该考虑其作用域和生命周期,确保其在所需范围内有效。
  4. 常量可以用于各种数据类型,包括基本类型、对象和指针。

常量在代码中起到了提高可读性、安全性和性能的作用,并且可以约束参数类型。合理使用常量可以使程序更加健壮和可维护。

2. 常指针

参考 c++ 常量指针与指针常量
常指针(const pointer)是指一个指针变量,它所指向的内存地址数据不可修改。

2.1 使用场景

  1. 保护对象的值不被修改:通过将指针声明为常指针,可以确保所指向的对象的值不被修改。这对于传递指针给其他函数或共享指针时很有用,可以防止函数或其他部分意外地修改对象的值。
int value = 10;
const int* ptr = &value;
// *ptr = 20;  // 错误,常指针不能修改所指向的对象的值
  1. 传递指针给只读函数:常指针可以用于传递指针给只读函数,这样可以确保函数内部不会修改所指向的对象的值,增加程序的安全性。
void printData(const int* ptr) {
    // *ptr = 20;  // 错误,只读函数不能修改所指向的对象的值
    std::cout << "Data: " << *ptr << std::endl;
}
  1. 与常对象配合使用:常指针可以与常对象配合使用,用于指向不可修改的对象。这样可以确保指针不会被用于修改对象的值。

完整代码:

#include 

void printData(const int* ptr) {
    std::cout << "Data: " << *ptr << std::endl;
}

int main() {
    int value = 42;
    const int* ptr = &value;

    printData(ptr);

    return 0;
}

3. 常函数

常函数(常成员函数)(const member function)是指在函数声明和定义中使用 const 关键字修饰的成员函数。常函数承诺不会修改对象的任何成员变量,它只能读取成员变量的值,但不能修改它们。这样可以确保在常对象上调用常函数时,对象的状态不会发生变化。

3.1 常函数特点

  1. 常函数不会修改对象的状态:常函数保证在其内部不会对类的成员变量进行修改操作。
  2. 常函数可以被常对象调用:常对象是指被声明为const的对象,在其上只能调用常成员函数。
  3. 常函数可以被非常对象调用:非常对象上既可以调用常成员函数,也可以调用非常成员函数。

代码:

#include 
#include 

using namespace std;

class Rectangle {
private:
    int width;
    int height;

public:
    Rectangle(int w, int h) : width(w), height(h) {}

    // 非常成员函数
    void setWidth(int w) {
        width = w;
        // this :  Rectangle *
    }

    // 声明为常成员函数
    int getWidth() const {
        return width;
        // this : const Rectangle *
    }


};

常函数只能去读成员的数据,不能修改成员的值;
常函数不能调用普通的函数,只能调用常函数;
普通成员函数中的this指针 Rectangle *,而常函数this指针是const Rectangle * ,就是常量指针,它所指向的内存地址数据不可修改

3.2 使用场景

  1. 保证数据成员不被意外修改:如果你希望某些成员变量在对象被视为"只读"时不能修改,你可以将相关操作定义为常成员函数。
  2. 提供只读访问接口:有时候你希望提供一些只读方法来获取类中的数据,而不允许通过这些方法进行修改操作。这种情况下,你可以将这些方法声明为常成员函数。

4. 常对象

常对象(常量对象)(Constant object)是指通过使用 const 关键字修饰的对象。常对象的值在创建后不能被修改,它的成员变量和成员函数都被视为常量,并且只能调用常函数。
代码:

#include 
#include 

using namespace std;

class Rectangle {
private:
    int width;
    int height;

public:
    Rectangle(int w, int h) : width(w), height(h) {}

    // 非常成员函数
    void setWidth(int w) {
        width = w;
        // this :  Rectangle *
    }

    // 声明为常成员函数
    int getWidth() const {

        return width;
        // this : const Rectangle *
    }


};

int main() {
    Rectangle rect0(20, 5);     // 非常对象
    //非常对象上可以调用非常成员函数
    rect0.setWidth(15);
    //非常对象上可以调用常成员函数
    int width0 = rect0.getWidth();
    cout << "Width: " << width0 << endl;

    const Rectangle rect(10, 5);  // 常对象
    // 调用常成员函数
    int width = rect.getWidth();
    cout << "Width: " << width << endl;

    // 无法调用非常成员函数
    // rect.setWidth(20);  // 编译错误

    return 0;
}

运行结果:

Width: 15
Width: 10

4.1 提示

如果想改某个变量的值,可以给某个变量加上 mutable关键字,表示这个变量是可变的。

#include 
#include 

using namespace std;

class Rectangle {
public:
    int width;
    mutable int height;


    Rectangle(int w, int h) : width(w), height(h) {}

    // 非常成员函数
    void setWidth(int w) {
        width = w;
        // this :  Rectangle *
    }

    // 声明为常成员函数
    int getWidth() const {
        //width = 10
        height = 30;
        return width;
        // this : const Rectangle *
    }


};

int main() {
    Rectangle rect0(20, 5);     // 非常对象
    //非常对象上可以调用非常成员函数
    rect0.setWidth(15);
    
    //非常对象上可以调用常成员函数
    int width0 = rect0.getWidth();
    cout << "Width: " << width0 << endl;

    const Rectangle rect(10, 5);  // 常对象
    // 调用常成员函数
    int width = rect.getWidth();
    cout << "Width: " << width << endl;
    rect.height =100;
    // 无法调用非常成员函数
    //rect.setWidth(20);  // 编译错误

    return 0;
}

把 height 声明为 mutable后 mutable int height;不仅在常函数可以改变成员变量的值:

   // 声明为常成员函数
    int getWidth() const {
        //width = 10
        height = 30;
        return width;
    }

而且常对象也可以改变成员函数的值

    const Rectangle rect(10, 5);  // 常对象
    // 调用常成员函数
    int width = rect.getWidth();
    cout << "Width: " << width << endl;
    rect.height =100;
    //rect.width = 200;

4.2 使用场景

  1. 数据保护:常对象用于保护数据不被修改。当某个对象的值在创建后不应该被改变时,可以将其声明为常对象,从而确保对象的值不会被意外修改。

  2. 代码安全性:常对象的使用可以提高代码的安全性。在多线程环境下,常对象可以防止并发访问导致的数据竞争和错误修改。此外,常对象还可以避免意外修改对象的值,增加代码的可靠性。

你可能感兴趣的:(c/c++,c++,开发语言)