c++中const关键字可以实现将一个变量或者函数,限定为只读不可进行修改的功能,它的作用是很大的,const 可以避免程序员在代码中意外修改某些本应保持恒定的值,并且它还可以限定指针或引用,使其无法通过它们修改所指向的对象,通过 const,可以增强代码的安全性和可读性,明确标识出不应被修改的部分,同时编译器会强制检查这些约束。

const int MAX_VALUE = 100;  // 必须初始化,后续不可修改
const double d = 120.15;

//如果我们修改了const修饰的变量,会直接报错
//error: assignment of read-only variable 'MAX_VALUE'
MAX_VALUE = 15;

下面再仔细讲讲,const在c++的各种应用

指针与引用的使用

const int MAX_VALUE = 100;  // 必须初始化,后续不可修改
int main(){
    int x = 10, a = 5;
    const int* y = &x;//能修改指针本身,但不能修改指向的内存
    int* const z = &x;//可以修改指向的内存,但不能修改指针本身
    *z = 20;
    // z = &a;//error: assignment of read-only variable 'z'
    y = &a;
    // *y = 30;//error: assignment of read-only location '* y'
  
    const int* const c = &MAX_VALUE;//指针本身和指向的内存都不能被修改
    // int* const d = &MAX_VALUE;//对于常量是不能被赋值给int* const类型指针的。
    return 0;
}

对于const与指针的组合有两种形式,分别是指向常量的指针(底层const)(const int* ptr;)与常量指针(顶层const)(int* const ptr;),常量指针是指指向的内容是常量的指针。这意味着您不能通过该指针修改它所指向的内存中的值,但指针本身可以被重新赋值,指向另一个地址,指针常量是指指针本身的地址是常量。这意味着指针一旦被初始化指向某个地址,就不能再被修改指向另一个地址。但是,您可以通过该指针修改它所指向的内存中的值。
引用基本上与指针是一样的,这里不过多介绍了

函数中的使用

void func1(const int& x) {
	//x是不能被修改的
}

const std::string* func2() {
	static std::string result = "Untitled";
	return &result;
}

std::string* s = func2();
//如果不是const的指针接受返回值会报错:error: cannot initialize a variable of type 'std::string *' (aka 'basic_string<char> *') with an rvalue of type 'const std::string *' (aka 'const basic_string<char> *')

const std::string func3() {
	static std::string result = "Untitled";
	return result;
}

const std::string& func4() {
	static std::string result = "Untitled";
	return result;
}

//下面两个都合法
std::string d1 = func3();
std::string d2 = func4();

std::string& d3 = func4();
//error: binding reference of type 'basic_string<...>' to value of type 'const basic_string<...>' drops 'const' qualifier

当我面以指针或者引用的形式,将参数传入函数时又不想函数改变我们的参数,这时候就可以使用const修饰,我们的函数将不能改变引用或指针指向的对象了,如果你想返回一个const的返回值,建议使用指针的形式返回const
函数返回的是一个临时副本,这个副本是const无法修改,但当将返回值赋给一个const变量时,会生成一个新的const副本const仅作用于临时副本,无法限制后续对新副本的修改。
在用引用返回时,会正常返回一个加了const的变量,但是如果我们的接受是普通的值变量,这时候会创建一个新的副本,这就导致了const的失效,如果想保持const需要用引用变量接受返回值,在日常使用中不建议返回引用,因为如果你返回了一个局部变量的引用,会导致悬垂引用

const std::string& func() {
    std::string local = "Hello";
    return local; // 错误:local在函数结束后销毁
}

类中的使用

class ConstClass{
public:
    ConstClass(){}
    ~ConstClass(){}
    int add() const {
        // a = 15;//报错
        // aaa();
        c++;.//合法
        return a + b;
    }
    void aaa() {
        a++;
    }
private:
    int a{10}, b{5};
    mutable int c{11};
};  

int main(){
    ConstClass obj;
    std::cout << obj.add() << std::endl;
    obj.aaa();
    const ConstClass obj2;
    obj2.add();
    return 0;
}

使用const修饰的成员变量,无法修改成员函数,也无法在内部调用非const函数,当我们创建对象实例时,const实例只能访问const成员函数,非const可以访问所有函数
如果我们想在const函数中修改成员变量,需要给成员变量添加mutable关键字,它会将成员变量设置为const函数可修改

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐