服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C++中多才多艺的 const

C++中多才多艺的 const

2022-01-12 13:56干燥剂 C/C++

在C++中,关键字const可以用来修饰任何作用域内的变量、函数参数、函数本体、函数返回值、成员函数、迭代器,也可以用来修饰指针本身和指针目标,可谓多才多艺,我们要详细了解其内部细节,以及逻辑奥秘,让这把多功能瑞士

1. 定义一个常全局变量

?
1
const int global = 100; // 初始化之后不可再赋值

这样的global实际上是一个常量,这是C++用来取代宏定义的其中一种措施,const常量有类型检测,提高编译器的效率。

2. 定义常指针

这有两个版本,分别是:

?
1
2
3
const int *p1 = &a; // p1不能修改它所指向的目标
int const *p1 = &a; // p1的另一种等价形式
int *const p2 = &a; // p2本身不可修改

上述代码中的p1经常被用作函数参数,用以限制指针的权限,在安全性方面功不可没。p2用的很少,我们很少需要一个本身指向不可变的指针

3. 定义一个STL的常迭代器

这也有类似的两个版本:

?
1
2
3
vector::const_iterator it1; // it1不能修改它所指代的目标对象
 
const vector::iterator it2; // it2本身不可修改

由于迭代器实际上就是广义指针,因此it1实际上相当于上述代码的p1,it2相当于上述代码的p2,同理it1用的较多,用来限制迭代器的权限。

4. 定义一个类的内部常成员

包括常成员数据和常成员方法:

?
1
2
3
4
5
6
7
8
9
10
11
class text
 
{
 
     const int aconst = 100; // 常成员数据,必须初始化
 
     void func(void) const; // 常成员方法,只能由常对象调用
 
     static int astatic;
 
};

类的常成员数据aconst,意味着类对象无法对其修改,这个很容易理解。至于类的常成员方法func就破费脑力了,语法上的理解是,func不能修改任何一个类对象的bit,这是显而易见的,这也正是C++标准对const成员方法的定义。\

来近距离看看func方法的使用:

?
1
2
3
4
5
6
7
8
9
10
11
int text::astatic = 100; // 类外初始化静态数据
 
void text::func(void) const // 类外定义const成员方法
 
{
 
astatic = 200; // 没毛病,astatic不是对象数据,此处可以被修改
 
aconst = 200; // 错误!const型函数不可修改类对象数据
 
}

定义如上的成员方法很重要,因为它明确地告诉了类的使用者,哪些函数可以修改类对象信息,哪些不会修改类对象信息。

func() 这样的函数const成员方法,只能被常对象调用,以确保不违反权限紧缩原则,比如:

?
1
2
3
4
text t1; // 普通对象t1
const text t2; // const型对象t2
t1.func(); // 错误!普通对象不可调用常成员方法
t2.func();

注意:函数本体的const属性是可以被视为重载的依据的,换句话说如果以上类text提供了non-const版本的func函数,那么t1将会自动调用non-const那个版本。

以上陈述似乎平淡乏味,但考虑C++语法规定的这种bit-wise特性的常成员在处理类成员指针,并且指针指向类外部内存时,情况也许会变得有趣。

5. bit-wise和logical-wise常特性

所谓bit-wise constness指的是类对象的内部内存意义上只读约束,而loigcal-wise指的是逻辑意义上的只读约束。编译器没有智能,它只能实现bit-wise意义上的约束,下面的例子讨论const成员 operator[ ] 的表现可以帮助理解:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
class text
{
     ... ...
     char &operator[ ](int pos) const;
private:
     char *p;
};
 
// const关键字保证了该成员方法只能被 const 对象调用
char &text::operator[ ](int pos) const
{
      return p[pos];
}

上述代码中,类text存储真正字符串的地方是指针 p 指向的内存区域,假设此时定义一个 const 型的常对象,那么它只能保证类内部信息(也就是p本身)不被修改,却无法保证其所指向的内存区域的安全性。来看下面的代码:

?
1
2
3
const text ct("abcd");
 
ct[0] = 'A'; // 一个被编译器允许却跟逻辑相悖的语句

此处ct是一个const型对象,从字面理解出发,我们应该认为ct对象是一个常量,我们应该无法通过任何方式修改其内部信息,但可惜,ct里面的字符串信息实际上并不存在在类内存区域中,于是就出现了可以对一个const型对象进行赋值的有趣现象。

解决以上问题也不难,可以改写 operator[ ] 成员方法的返回值类型:

?
1
const char &operator[ ](int pos) const;

此时就再也不能对 ct[0] 赋值了,但这只是个个例,关键我们要掌握的内容是:如果我们的类对象拥有成员指针,那么一般意义上的const成员方法只能保证bits-wise的常量性(即保证类对象内部的内存信息不被修改),但无法保证所谓的 logical-wise的常量性(即保证逻辑上哪些信息不被修改)。

到此这篇关于C++中的 const的文章就介绍到这了,更多相关C++中的const内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://juejin.cn/post/7000712285006561287

延伸 · 阅读

精彩推荐
  • C/C++C语言实现双人五子棋游戏

    C语言实现双人五子棋游戏

    这篇文章主要为大家详细介绍了C语言实现双人五子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    两片空白7312021-11-12
  • C/C++深入C++拷贝构造函数的总结详解

    深入C++拷贝构造函数的总结详解

    本篇文章是对C++中拷贝构造函数进行了总结与介绍。需要的朋友参考下...

    C++教程网5182020-11-30
  • C/C++c/c++内存分配大小实例讲解

    c/c++内存分配大小实例讲解

    在本篇文章里小编给大家整理了一篇关于c/c++内存分配大小实例讲解内容,有需要的朋友们可以跟着学习参考下。...

    jihite5172022-02-22
  • C/C++c/c++实现获取域名的IP地址

    c/c++实现获取域名的IP地址

    本文给大家汇总介绍了使用c/c++实现获取域名的IP地址的几种方法以及这些方法的核心函数gethostbyname的详细用法,非常的实用,有需要的小伙伴可以参考下...

    C++教程网10262021-03-16
  • C/C++C语言main函数的三种形式实例详解

    C语言main函数的三种形式实例详解

    这篇文章主要介绍了 C语言main函数的三种形式实例详解的相关资料,需要的朋友可以参考下...

    ieearth6912021-05-16
  • C/C++OpenCV实现拼接图像的简单方法

    OpenCV实现拼接图像的简单方法

    这篇文章主要为大家详细介绍了OpenCV实现拼接图像的简单方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    iteye_183805102021-07-29
  • C/C++关于C语言中E-R图的详解

    关于C语言中E-R图的详解

    今天小编就为大家分享一篇关于关于C语言中E-R图的详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看...

    Struggler095962021-07-12
  • C/C++使用C++制作简单的web服务器(续)

    使用C++制作简单的web服务器(续)

    本文承接上文《使用C++制作简单的web服务器》,把web服务器做的功能稍微强大些,主要增加的功能是从文件中读取网页并返回给客户端,而不是把网页代码...

    C++教程网5492021-02-22