c++ const总结

c++ const总结,第1张

1.const基本

const,常量限定符,在c++中非常常见,用来限定特定变量,并告诉编译器,该变量不能修改。const用得好,能避免对不应修改的变量进行修改,提高代码整体的可靠性。

2.定义常量

const最常见的用法是定义常量了,比如

const int a = 0;
int const a = 0;

以上两种写法都没有问题。

void func1(const char c) {
    cout<<"c is: "<
3.与define区别

define也能定义所谓”常量”。那么const与define的区别在哪里呢?
1 #define宏是在代码预处理阶段展开。
而const常量是在编译运行阶段才使用

2 #define只是简单的字符串替换,没有变量类型,也不能进行安全检查。
而const是具有类型的,编译器可以进行类型安全检查。

3 #define宏仅仅是展开进行代码替换,不会分配内存。有多少地方使用,就展开多少次。宏定义阶段不会分配内存,变量定义阶段才分配内存。

4 define只做替换,不做计算,也不会针对表达式进行求解。

5 const 可以节省空间,避免不必要的内存分配。从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝(因为是全局的只读变量,存在静态区),而 #define定义的常量在内存中有若干个拷贝。

4.const与指针

与指针相关的const有这么几种:

const char *p;
char const *p;
char *const p;
const char *const p;

在前面的文章中我们已经分析过了,第一、二种的写法本质相同,都是常量指针,意思是指针指向的数据为一个常量,不可以改变,但指针指向的地址可以改变。第三种为指针常量,指针指向的地址不可以改变,但地址里面的内容可以改变。而第四种则是指向常量的指针常量,指针的地址与指向的内容均不可改变。

常量指针可以不用初始化赋值,但是不能改变指向的值。

void func() {
    const int *p;
    const int a = 1;
    p = &a; 
    cout<

另外一点,不能使用void指针类型保存const对象的地址,可以使用const void类型的指针保存const对象的地址。

void func() {
    const int n = 1;
    const void *p = &n;
    cout<

同时,const类型的指针可以取非const类型对象的地址。如果我们把前面的例子稍作修改:

void func() {
    const int *p;
    int a = 1;
    p = &a; 
    cout<

这样也是可以的。

5.const与函数返回值

const可以用于函数的返回值中

const char* func()

上面表示,返回的类型为char型常量指针,指针指向的内容不能发生改变。

char *const func()

上面表示返回的是指针常量。

const char func()

上面这种方式,const是冗余的。因为一般情况下,函数返回值都是赋值给其他变量,没必要再加const。

int func1() {
    const int n = 1;
    return n;
}

const int func2() {
    int n = 1;
    return n;
}

上面两种写法,效果完全是一样的。所以对于返回类型是基础类型的函数,一般不会带上const。

6.const与函数参数

函数参数用const修饰,主要是防止传入的参数表示的数据在函数实体内被改变。因此,如果参数是值传递的方式,传递的仅仅是实参副本,即使数据在函数内改变,实参的值也不会受影响。比如

void func1(const int n) {
    n = 2; // error
}

上面的代码,IDE会报错提示不能修改n的值,但是从实际上来说,没有任何作用。

如果传的参数是指针,const修饰时表示在函数体内不能修改该指针所指的内容,起到保护数据的作用。看一个字符串复制的案例:

void copy_string(char const *source, char *des) {
    strcpy(des, source);
}

void func2() {
    char const *src="hello";
    char des[10];
    copy_string(src, des);
    cout<<"src is: "<

运行结果为:

src is: hello
des is: hello

上面使用const修饰输入的指针,目的就是防止在函数内该指针被修改。

而当const修饰引用时,

 void f(MyClass myclass)

传入的参数是myclass对象副本,要使用构造函数来构造其副本,并且使用结束以后还要用析构函数来析构掉该对象。如果这个对象本身比较复杂,会造成时间与空间的浪费。所以在这种情况下,如果函数参数为类的对象,一般使用引用。而使用引用的问题在于,函数参数的引用可能会修改对象内的成员变量。所以,我们会大量看到如下形式的函数声明

 void f(const MyClass &myclass)

通过const修饰,就可以避免引用被修改。

7.类与const

我们还经常见到如下的函数签名形式:

int get_xxx() const {}

上面这种函数声明,一般都出现在类中。在类中将成员函数用const在后面修饰,说明在该函数内,不能修改对象的成员变量,并且不能调用非const函数。

在java中,对象成员变量的处理方式一般都是通过get/set方法来进行读取与设置。其中get方法是读取,set方式是设置。如果我们把类似get方法这种函数都加上const修饰符进行标识,就可以提高程序的可读性。同时,还能提高代码的健壮性。一旦我们在const函数中试图修改成员变量的值,编译器就会提前给我们错误提示。

又因为const函数不能修改成员变量,而非const有可能修改成员变量,所以const函数只能调用const函数,也就是很自然的逻辑。

看下面一个例子:

class MyClass {
    private:
        int n;
    public:
        int get_num() const {
            return n;
        }
        void set_num(int n) {
            this->n = n;
        }
};

上面get_num方法因为是读取成员变量,所以可以加const修饰。而set方法是设置值,改变了成员变量,所以不能加const修饰。

参考文献:
1.https://www.jianshu.com/p/4d9f30abc3e9

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/langs/716957.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-25
下一篇 2022-04-25

发表评论

登录后才能评论

评论列表(0条)