C/C++:CV(const 与 volatile)属性的理解

C/C++提供多种声明变量和函数存储持续性、作用域和链接性的关键字,有些被称为存储说明符(store class specifier)或 cv 限定符(cv-qualifier), cv 限定符可出现于任何类型说明符(包括声明文法的 声明说明符序列)中,以指定被声明对象或被命名类型的常量性(constness)或易变性(volatility)。

  • const ——定义类型为常量。
  • volatile ——定义类型为易变。

const用途:

  1. 声明符号常量,在声明符号常量的同时必须进行初始化,否则就没有机会再给符号常量赋值了。如果在声明符号常量时没有初始化,那么该常量的值将是不确定的,且无法修改!例如:
const int months = 12;
const bool flag=true;
注意

在C语言中,用const修饰的变量,其本质上还是个变量,只是它不允许作为左值存在,也就是不应该对该变量进行直接赋值修改该变量,但是这不意味着该变量的值就无法修改。我们可以通过指针来修改该变量的值:

#include <stdio.h>
int main()
{
	const int a = 5;
	int* p = (int*)&a;
	
	printf("a = %d\n",a); //5
	
	*p = 10;
	printf("a = %d\n",a); //10
	return 0;
}

但是在C++中,执行的结果都是5,因为在C++编译的过程,当碰到用const修饰的变量时,编译器是直接将变量的值和变量的符号对应起来一起存到符号表中,例如const int a = 5;在符号表中就会将a和5对应起来,在编译的过程中,当碰到printf(“a = %d\n”,a); 时,为用 5 直接将 a 替换掉。在C++中,编译器不会为a分配存储空间,在C语言中就会为a分配存储空间,所以在C编译器中,就可以通过指针来改变用const修饰的变量。如果对const常量使用了extern或者取地址符&。C++会为常量分配存储空间,但是却不会使用该存储空间中的值。所以C++中的 const 更像编译阶段的 #define,但是const可以指明类型,也可以用于数组

  1. 修饰常量的作用域和链接性。(C++)
  • C和C++中全局 const 变量的作用域相同,都是当前文件,但是它们的可见范围不同:C语言中 const 全局变量的可见范围是整个程序,在其他文件中使用 extern 声明后就可以使用;而C++中 const 全局变量的可见范围仅限于当前文件,在其他文件中不可见,所以它可以定义在头文件中,多次引入后也不会出错。

注意:在C++中,可以使用extern关键字来增大 C++ 全局 const 变量的可见范围:extern const int time = 1;这样在一个文件中声明的常量time就可以在另外一个文件中使用,需要注意的是其他文件中使用time时必须使用extern:extern int time;因为time在多个文件中共享,所以只能有一个文件对其进行初始化!

volatile用途

改善编译器的优化能力。volatile 影响编译器编译的结果,volatile指出 变量是随时可能发生变化的,与volatile变量有关的运算,不要进行编译优化,以免出错,(VC++ 在产生release版可执行码时会 进行编译优化,加volatile关键字的变量有关的运算,将不进行编译优化。)当要求使用 volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存。

volatile int i=10;
int a = i;
...
// 其他代码,并未明确告诉编译器,对 i 进行过操作
int b = i;

volatile 指出 i 是随时可能发生变化的,每次使用它的时候必须从 i的地址中读取,因而编译器生成的汇编代码会重新从i的地址读取数据放在 b 中。而优化做法是,由于编译器发现两次从 i读数据的代码之间的代码没有对 i 进行过操作,它会自动把上次读的数据放在 b 中。而不是重新从 i 里面读。这样以来,如果 i是一个寄存器变量或者表示一个端口数据就容易出错,所以说 volatile 可以保证对特殊地址的稳定访问。

a.cpp:9:49: error: non-member function ‘Complex operator-(Complex&)’ cannot have cv-qualifier 9 | friend Complex operator-( Complex &c3 ) const;//重载双目运算符'-' | ^~~~~ a.cpp:25:9: error: no declaration matches ‘Complex Complex::operator-=(Complex&) const’ 25 | Complex Complex::operator-=(Complex &c2)const | ^~~~~~~ a.cpp:8:17: note: candidate is: ‘Complex Complex::operator-=(Complex&)’ 8 | Complex operator-=( Complex &c2 ); //重载双目运算符'-=' | ^~~~~~~~ a.cpp:3:7: note: ‘class Complex’ defined here 3 | class Complex | ^~~~~~~ a.cpp:31:9: error: no declaration matches ‘Complex Complex::operator-(Complex&) const’ 31 | Complex Complex::operator-(Complex &c3)const | ^~~~~~~ a.cpp:31:9: note: no functions named ‘Complex Complex::operator-(Complex&) const’ a.cpp:3:7: note: ‘class Complex’ defined here 3 | class Complex | ^~~~~~~ a.cpp: In function ‘int main(): a.cpp:44:12: error: no match for ‘operator-’ (operand types are ‘Complex’ and ‘Complex’) 44 | c3 = c1-c2; | ~~^~~ | | | | | Complex | Complex In file included from /usr/include/c++/11/bits/stl_algobase.h:67, from /usr/include/c++/11/bits/char_traits.h:39, from /usr/include/c++/11/ios:40, from /usr/include/c++/11/ostream:38, from /usr/include/c++/11/iostream:39, from a.cpp:1: /usr/include/c++/11/bits/stl_iterator.h:577:5: note: candidate: ‘template<class _IteratorL, class _IteratorR> constexpr decltype ((__y.base() - __x.base())) std::operator-(const std::reverse_iterator<_IteratorL>&, const std::reverse_iterator<_IteratorR>&)’ 577 | operator-(const reverse_iterator<_IteratorL>& __x, | ^~~~~~~~ /usr/include/c++/11/bits/stl_iterator.h:577:5: note: template argument deduction/substitution failed: a.cpp:44:13: note: ‘Complex’ is not derived from ‘const std::reverse_iterator<_IteratorL>’ 44 | c3 = c1-c2; | ^~ In file included from /usr/include/c++/11/bits/stl_algobase.h:67, from /usr/include/c++/11/bits/char_traits.h:39, from /usr/include/c++/11/ios:40, from /usr/include/c++/11/ostream:38, from /usr/include/c++/11/iostream:39, from a.cpp:1: /usr/include/c++/11/bits/stl_iterator.h:1693:5: note: candidate: ‘template<class _IteratorL, class _IteratorR> constexpr decltype ((__x.base() - __y.base())) std::operator-(const std::move_iterator<_IteratorL>&, const std::move_iterator<_IteratorR>&)’ 1693 | operator-(const move_iterator<_IteratorL>& __x, | ^~~~~~~~ /usr/include/c++/11/bits/stl_iterator.h:1693:5: note: template argument deduction/substitution failed: a.cpp:44:13: note: ‘Complex’ is not derived from ‘const std::move_iterator<_IteratorL>’ 44 | c3 = c1-c2; | ^~ a.cpp:9:24: note: candidate: ‘Complex operator-(Complex&)’ 9 | friend Complex operator-( Complex &c3 ) const;//重载双目运算符'-' | ^~~~~~~~ a.cpp:9:24: note: candidate expects 1 argument, 2 provided 确
最新发布
05-07
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值