C/C++ 语言 const 关键字
1. Constants - 常量
ANSI C 允许声明常量,常量的样子和变量完全一样,只是它们的值不能被修改。使用 const 关键字声明常量:
const int a;
int const a;
两条语句都把 a 声明为一个整数,它的值不能被修改。可以选择自己觉得容易理解的一种,并一直坚持使用同一种形式。因为 a 的值无法被修改,所以无法把任何东西赋值给它。
使得 a 拥有初始值的两种方法:
- 可以在声明时对它进行初始化,
const int a = 15;
int const a = 15;
- 在函数中声明为
const 的形参在函数被调用时会得到实参的值。
int *pi;
pi 是一个普通的指向整型的指针。
const int *pci;
int const *pci;
pci 是一个指向整型常量的指针。可以修改指针的值,但不能修改它所指向的值。const 修饰指针指向的内容,则内容为不可变量。
int *const cpi;
cpi 为一个指向整型的常量指针。指针是常量,它的值无法修改,但你可以修改它所指向的整型的值。const 修饰指针,则指针为不可变量。
int const *const cpci;
const int *const cpci;
cpci 无论是指针本身还是它所指向的值都是常量,不允许修改。const 修饰指针和指针指向的内容,则指针和指针指向的内容都为不可变量。
当你声明变量时,如果变量的值不会被修改,你应当在声明中使用 const 关键字。这种做法不仅使你的意图在其他阅读你的程序的人面前得到更清晰的展现,而且当这个值被意外修改时,编译器能够发现这个问题。
#define 指令是一种创建名字常量的机制。下面的两个声明都为 5 这个值创建了名字常量。
#define MAX_ELEMENTS 5
const int max_elements = 5;
在这种情况下,使用 #define 比使用 const 变量更好。因为只要允许使用字面值常量的地方都可以使用前者,const 变量只能用于允许使用变量的地方。
名字常量非常有用,因为它们可以给数值起符号名,否则它们就只能写成字面值的形式。用名字常量定义数组的长度或限制循环的计数器能够提高程序的可维护性。如果一个值必须修改,只需要修改声明就可以了。修改一个声明比搜索整个程序修改字面值常量的所有实例要容易得多,特别是当相同的字面值用于两个或更多不同目的的时候。
1.1 Example
//============================================================================
// Name : Yongqiang Cheng
// Author : Yongqiang Cheng
// Version : Version 1.0.0
// Copyright : Copyright (c) 2020 Yongqiang Cheng
// Description : Hello World in C++, Ansi-style
//============================================================================
#include <stdio.h>
int main()
{
int val = 123;
const int *ptr = &val;
printf("BEFORE: %d\n", *ptr);
val = 456;
printf("AFTER: %d\n", *ptr);
return 0;
}
BEFORE: 123
AFTER: 456
请按任意键继续. . .
指向常量的指针是不可以通过这个指针去修改它所指向的值。
2. 常量指针和指向常量的指针
pstr 的定义如下:
// Initializing a pointer array
const char *pstr[]{
"000000",
"111111",
"222222",
"333333",
"444444",
"555555"
};
数组中的各个指针初始化为字符串字面值的地址。字符串字面值的类型是 const char 数组,因此我们是在 const 的指针中存储 const 数组的地址。pstr 指针数组的元素指向const 字符串。如果现在试图修改这些字符串,则在编译时编译器将这标志为错误。
在下面的语句中,没有改变指针数组元素指向的对象的值,改变的只是 pstr[0] 中存储的指针的值。
pstr[0] = pstr[1];
在下面的语句中,字符串中的字符不能修改,数组中的地址也不能修改。
// Array of constant pointers to constants
const char *const pstr[]{
"000000",
"111111",
"222222",
"333333",
"444444",
"555555"
};
- 指向常量对象的指针
- 指向某个对象的常量指针
- 指向常量对象的常量指针
在指向常量对象的指针中,不能修改被指向的对象,但可以使指针指向其他对象:
int value{ 5 };
const int *pvalue{ &value };
*pvalue = 6; // Will not compile!
pvalue = nullptr; // OK
在指向某个对象的常量指针中,不能修改指针中存储的地址,但可以修改指针指向的对象:
int value{ 5 };
int *const pvalue{ &value };
*pvalue = 6; // OK
pvalue = nullptr; // Will not compile!
在指向常量对象的常量指针中,指针和被指向的对象都定义成常量,都不能修改:
int value{ 5 };
const int *const pvalue{ &value };
*pvalue = 6; // Will not compile!
pvalue = nullptr; // Will not compile!
一般来说,为了正确地解释更复杂的指针类型,只需要从右向左读。类型 const char * 是一个指向字符的指针,且这些字符是 const 。类型 char *const 是一个指向字符的 const 指针。
2.1 Example
//============================================================================
// Name : Yongqiang Cheng
// Author : Yongqiang Cheng
// Version : Version 1.0.0
// Copyright : Copyright (c) 2020 Yongqiang Cheng
// Description : Hello World in C++, Ansi-style
//============================================================================
#include <iostream>
int main()
{
// Initializing a pointer array
const char *pstr[]{
"000000",
"111111",
"222222",
"333333",
"444444",
"555555"
};
const char *pstart{ "Your lucky star is " };
int dice{};
std::cout << std::endl
<< "Pick a lucky star!"
<< "Enter a number between 1 and " << _countof(pstr) << ": ";
std::cin >> dice;
std::cout << std::endl;
if (dice >= 1 && dice <= _countof(pstr)) // Check input validity
{
std::cout << pstart << pstr[dice - 1] << std::endl;
}
else
{
std::cout << "Sorry, you haven't got a lucky star.\n";
}
std::cout << std::endl;
return 0;
}
Pick a lucky star!Enter a number between 1 and 6: 5
Your lucky star is 444444
请按任意键继续. . .
References
Ivor Horton’s Beginning Visual C++ 2013 - 4.3.7 (美) Ivor Horton 著, 李周芳, 江凌 译. Visual C++ 2013 入门经典[M]. 第 7 版. 清华大学出版社, 2015. http://www.wrox.com/WileyCDA/WroxTitle/productCd-1118845714.html
Pointers on C - 3.4 https://www.cs.rit.edu/~kar/pointers.on.c/index.html
cppreference.com - C++ reference https://en.cppreference.com/w/cpp/language/cv
|