设为首页 加入收藏

TOP

68.C++中的const(三)
2023-07-23 13:35:42 】 浏览:112
Tags:68.C const
* const p32 = &k2; //指向常量的指针常量 }

1.4顶层与底层const

??任意常量对象为顶层const,包括常量指针;指向常量的指针和声明const的引用都为底层const

??顶层const(top-level const)表示指针本身是个常量int* const ptr=&m;

??此时指针不可以发生改变,但是指针所指向的对象值是可以改变的

??底层const(low-level const)表示指针所指的对象是常量const int* ptr=&m;

??此时指针可以发生改变,但是指针所指向的对象值是不可以改变的

??顶层const可以表示任意的对象是常量(指针、引用、int、double都可以)

??于是只有指针和引用等复合类型可以是底层const

??执行对象的拷贝构造时,常量是顶层const还是底层const差别明显

??顶层const并不会有任何影响

进行拷贝操作的时候,仅仅只是从右值(顶层const)拷贝一个值并给自己赋值,虽然右值是一个不可变的量,但是貌似对我自己的拷贝完全没有影响吧

const int m = 10;
int n = m;
int* const ptr2 = &n;
int* ptr3 = ptr2;
int i= 0; 
int *const p1 = &i;//不能改变p1的值,这是一个顶层const
const int ci = 42;//不能改变ci的值,这是一个顶层const
const int *p2 = &ci;//允许改变p2的值 这是一个底层const
const int *const p3 = p2;//靠右的const是顶层const, 靠左的是底层
const const int &r = ci;//用于声明引用的const都是底层const

??当执行对象的拷贝操作时,常量是顶层const还是底层const区别明显。 其中,顶层const不受什么影响:

i = ci;//正确:拷贝ci的值,CI是 一个顶层const, 对此操作无影响
p2 = p3;//正确:p2和p3指向的对象类型相同,p3顶层const的部分不影响

??执行拷贝操作并不会改变被拷贝对象的值,因此,拷入和拷出的对象是否是常量都没什么影响。

??另一方面,底层const的限制却不能忽视。当执行对象的拷贝操作时拷入和拷出的对象必须具有相同的底层const资格,或者两个对象的数据类型必须能够转换。非常量可以转换成常量,反之则不行:

int *p = p3;//错误:p3包含底层const的定义,而p没有
p2 = p3;//正确:p2和p3都是底层const ??????????
p2 = &i;//正确:int*能转换成const int* 
int &r = ci;//错误:普通的int&不能绑定到int常量上
const int &r2 = 1;//正确:const int&可以绑定到一个普通int上

??p3既是顶层const也是底层const,拷贝p3时可以不在乎它是一个顶层const,但是必须清楚它指向的对象得是一个常量。因此,不能用p3去初始化p, 因为p指向的是一 个普通的(非常量)整数。 另一方面,p3的值可以赋给p2,是因为这两个指针都是底层const,尽管p3同时也是一个常量指针(顶层const), 仅就这次赋值而言不会有什么影响。

原文链接:https://blog.csdn.net/m0_64860543/article/details/128269607

2.const 函数形参

??我们已经了解了变量中const修饰符的作用,调用函数就会涉及变量参数的问题,那么在形参列表中const形参与非const形参有什么区别呢?

2.1 const 修饰普通形参

同样,先来看看普通变量:

void fun(const int i)
{
	i = 0;
    cout << i << endl;
}

void fun(int i)
{
	i = 0;
    cout << i << endl;
}

int main()
{
    const int i = 1;
    fun(i);
    return 0;
}

??形参的顶层 const 在初始化时会被忽略,所以上面定义的两个函数实际上是一个函数。编译时会出现void fun(int) previously defined here错误。

  • 由于普通变量是拷贝传值,所以const int实参可以传给int形参。

  • 与普通 const 变量一样,第一个 fun 中的形参 i 只可读;第二个function中的 i 则可读可写。

2.2 const 修饰指针形参

??与 const 指针变量一样,指向常量的指针形参指向的值不能修改;本身就是常量的指针形参不能指向其他变量;指向常量的常量指针形参指向的值不能被修改,也不能指向其他变量。

#include<iostream>
using namespace std;
void fun(const int* i)
{
    cout << *i << endl;
}

void fun(int* i)
{
    *i = 0;
    cout << *i << endl;
}

int main()
{
    const int i = 1;
    //调用 fun(const int* i),没有 fun(const int* i),则会编译报错,因为没有匹配形参的函数。
    fun(&i);  
    int j = 1;
    //调用 fun(int* i),没有 fun(int* i),则会调用 fun(const int* i),此时 j 的值不会被改变
    fun(&j);  
    return 0;
}

此外,形参的底层 const 在初始化时不会被忽略,所以上面的两个函数是不同的函数,即重载函数,上面例子编译并不会报错,若果再加上一个void fun(int *const i)就会报错,因为这个函数定义里面 i 是顶层 const。

2.3 const 修饰引用形参

??与const引用一样,const引用不会改变被引用变量的值。

#include<iostream>
using namespace std;
void fun(const int& i)
{
    cout << i << endl;
}

void fun(int& i)
{
    i = 0;
    cout << i << endl;
}

int main()
{
    const int i = 1;
    //调用 fun(const int& i),没有 fun(const int& i),则会编译报错,因为没有匹配形参的函数。
    fun(i);
    int j = 1;
    //调用 fun(int& i),没有 fun(int& i),则会调用 fun(const int& i),此时 j 的值不会被改变
    fun(j);
    return 0;
}

由于 const 引用也是底层 const ,所以上面两个函数是不同的函数,即重载函数,编译并不会报错。

3.类常量成员函数

??面向对象程序设计中,为了体现封装性,通常不允许直接修改类对象的数据成员。若要修改类对象,应调用公有成员函数来完成。为了保证const对象的常量性,编译器须区分试图修改类对象

首页 上一页 1 2 3 4 5 下一页 尾页 3/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Leetcode Practice -- 数组 下一篇C++/Qt网络通讯模块设计与实现(三)

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目