C++变量

C++变量

一、变量的声明和定义

1.1 变量的定义

变量定义的格式为
type name; // 定义type类型变量name,默认初始化
或者:
type name = value; // 定义type类型变量name,并设置初始值为value
类型说明符 变量名
例如:

// 下面的定义没有给初始值,所以变量会被默认初始化
int a;
bool b;
char c;
double d;
long l;
short s;
// 定义整型变量并设置初始值为1
int a = 1;

注意:定义在函数体外的内置类型变量会被初始化为0;
定义在函数体内部的内置类型变量不会被初始化,所以值是未定义的;使用该值可能会发生错误。

1.2 初始化和赋值

初始化是创建变量的时候赋予其一个初值;
赋值是把对象的当前值擦除,赋予其一个新值;

1.3 声明和定义的关系

声明是指把名字告知程序,使得程序知道该名字。
定义是负责创建与名字关联的实体。

声明和定义都规定了变量的类型和名字,但是声明不会为变量申请存储空间,定义会为变量申请内存空间,也可能会为变量赋初值。

包含了显示初始化的声明自动变为定义。

变量只能被定义依次,但是可以多次声明。

声明变量的方法:

extern int i; //声明一个整型变量i
int j;	//声明并定义j
extern int k = 0;	//声明并定义k

2 标识符

C++标识符右字母、下画线、数组组成;
必须以字母或者下画线开头,不能数字开头,长度没有限制,大小写敏感。

3 变量的作用域

变量的作用域起始于名字的声明语句,以声明语句所在的作用域末端结束

int i;	//i是一个全局变量,在整个程序中有效
void test()
{
	int i;	//i是一个局部变量,在函数test的函数体内有效,同时这个局部的变量i覆盖了上面的全局变量i,如果在函数体内想要使用全局的i可以加上全局作用域符::i来使用
}

4 符合类型变量

4.1 引用

引用就是给变量起一个别名,用法变量原来的名字是完全相同的。
格式:

int i = 0;
int& r1 = i;	//r是i的一个引用,也就是一个别名
int& r2 = r1;	//正确,r2是i的另一个引用,r2,r1,i代表相同的变量

定义引用时必须初始化,否则无法知道引用的是哪个变量,编译出错。

引用只能绑定在对象上,不能绑定字面值或者表达式的计算结果。

4.2 指针

指针是指向某种类型的变量,其值代表其指向变量的地址。
指针本身也是一个对象,允许赋值和拷贝,可以执行不同的对象。
指针在定义时可以不给初始值;
格式:

int* p; // p是一个int型指针,指向一个int型的对象
int i = 0;
int* pi = &i; //p是一个int型指针,指向i

4.2.2 通过指针访问对象

如果想要通过指针来访问(获取值,修改值等)对象,对指针使用*(解引用)操作符就可以

int i = 0;
int* p = &i;
*p = 10;	// 把p指向的对象的值赋为10,此时i的值变为10;
cout << *p << endl;	// 把p指向对象的值打印到标准输出流,屏幕输出10;

4.2.3 指针赋值

不使用*(解引用)运算符时,给指针赋值,是改变了指针所指向的地址

int i = 0;
int* p = &i;	// 让p指向i;
int a = 10;
p = &a;		// 让p重新指向a;

4.2.4 指向指针的指针

因为引用本身不是对象,所以指针不能指向引用,但是指针可以指向指针

int i = 0;
int* p = &i;	// p是指针,指向int类型的i
int** pp = &p;	// pp是指针的指针,指向int*类型的p

5 const修饰符

const 是常量修饰符,有const修饰的变量,其值不能被修改;实现只读效果
const修饰的变量,其值不能被修改,所以必须要在定义的时候进行初始化。

const int i = 42;// 正确,i是一个常变量,其值只读,不可修改
const int j;	// 错误,常变量必须在定义时初始化

默认状态下,const对象只在本文件内有效,如果想在多个文件之间共享const对象,必须在变量的定义之前添加extern关键字。

5.1 const的引用

const的引用,可以绑定任意表达式作为初始值(非const的引用只能绑定到对象上),,const引用可以绑定非常量对象,字面值,甚至是一般表达式。

int i = 10;
const int& r1 = i;	//正确
const int& r2 = r1 * 10;	//正确
const int& r3 = 42;	//正确
int& r4 = r1 * 10;	//错误

5.2 const和指针

5.2.1 指向常量的指针

指针可以指向常量,指向常量的指针,不能用于改变其所指对象的值,如果想存放常量对象的地址,只能使用指向常量的指针。

const int i = 10;
int* pi = &i;	// 错误,pi不是一个指向常量的指针,但是其指向的变量是一个常变量
const int* ptr = &i;	//正确,ptr是一个指向常整型变量的指针
*ptr = 20;	// 错误,不能对指向常量的指针执行的对象进行赋值

const修饰的指针,可以指向非常量,但是此时不能通过指针修改指向对象的值

double d = 3.14;
const double* p = &d;	//正确,p是指向d的一个指针,但是通过这个指针只能对d进行只读操作,不能进行修改操作
d = 2.718;	// 此时,可以通过其他方法修改d的值

5.2.2 const指针

指针本身是一个变量,const也可以作用与指针本身,此时指针为常量指针,也就是指针的值(指针指向的地址)不能变化。

int i = 10;
int a = 20;
int* const p = &i;	// 正确,p指向i,同时p的值不能改变,也就是p不能重新指向别的对象
*p = 20;	// 正确,可以通过指针修改指向对象的值
p = &a;	//错误,p是const类型的指针,其值(指向的地址)不能被修改

5.2.3 顶层const和底层const

对于指针来说,const可以用来说明指针本身是常量(顶层const)或者指针指向常量(底层const)
对于引用来说,const全部都是底层const(也就是说是对常量的引用)

int i = 10;
const int* p1 = &i;	//	底层const,用来说明指针指向常量(只读,不能通过指针修改指向对象的值)
int* const p2 = &i;	//	顶层const,用来说明指针是一个常量(不能指向别的地址)
const int& r1 = i;	//	底层const,用来说明是对常量的引用(只读,不能通过引用来修改对象的值)

一般地,在赋值时,顶层const不对赋值产生影响,但是底层const的变量不能赋值给非底层const的变量

int i = 10;
const int* p1 = &i;	
int* const p2 = &i;
int* p3 = p1;	// 错误,p1具有底层const,其指向的是常量(只读,不对其指向的对象进行修改),而p3不具有底层const,其指向的不是常量(非只读,可以通过其对指向的对象进行修改)
int* p4 = p2;	// 正确,p2具有顶层const,代表p2是常指针,可以把p2指向的地址赋给p4

5.2.4 constexpr变量

常量表达式是指值不会改变,并且在编译过程就能得到计算结果的表达式。
C++11允许将变量声明为constexpr类型以便由编译器验证变量的值是否是一个常量表达式。声明为constexpr的变量一定是一个常量,并且必须用常量表达式初始化

constexpr int i = 20;
constexpr int limit = i + 1;
constexpr int sz = size();	//当size是一个constexpr函数时正确

constexpr作用于指针时,仅对指针有效,与指针所属的对象无关

const int* p = nullptr;	//p是一个指向常量整型的指针
constexpr int* q = nullptr;	// q是一个指向整型的常量指针,constexpr把它定义的对象限定为顶层const

6.变量类型

6.1 类型别名

typedef unsigned int size_t;	//size_t是unsigned int 的别名
using ui = unsigned int;		//ui是unsigned int的别名
size_t sz = 10;		// sz是unsigned int类型变量
ui i = 10;		// i是unsigned int类型变量

指针类型的别名和const一起使用时,const会被认为是顶层const而不是底层const

typedef char* pstchar;
const pstchar pc;	// 此时,pc是常量指针,而不是指向常量的指针,const是顶层const

6.2 auto说明符

当要将一个复杂表达式的结果赋值给某个变量,必须要清楚的知道表达式结果的类型并在声明是写出该类型,对于比较复杂的表达式,并不是一件容易的事。
C++11新标准引入了auto类型说明符,可以让编译器帮助判断表达式结果类型

auto a = 10;	// a是整型
auto sz = 0, pi = 3.14;	//	这种声明是错误的,因为编译器判断0是整型,3.14是double型,无法确定auto实际应该代表的类型

auto一般会忽略顶层的const,同时底层的const会保留

int i = 0;
const int ci = 10, &cr = i;
auto a = ci;	// ci具有顶层const,auto会忽略,a是一个整型变量
auto b = cr;	// cr是ci的引用,相当于把ci赋值给b,b是一个整型变量
auto c = &i;	// c是一个整型指针,指向整型变量
auto d = &ci;	// d是一个指向常量的指针,因为ci具有底层const,

如果需要auto推断出的类型具有顶层const,需要明确指出:

const auto e = ci;	// e是一个常整型(const int)

6.3 decltype类型指示符

decltype 可以根据表达式返回类型,不用计算表达式的值

decltype(size()) sz = 10;	// sz的类型是size函数的返回值的类型

decltype在得出变量类型时会保留其顶层const和引用

const int ci = 0, &cr = ci;
decltype(ci) x = 0;	// x是const int类型
decltype(cr) y = x; // y是const int&类型,绑定到x
decltype(cr) z;	// 错误,z是引用,必须初始化

decltype的表达式如果是对指针解引用操作,那么得到的将是一个引用类型

int i = 10;
int* p = &i;
decltype(*P) a = i;	//a是一个整型的引用,如果不初始化,会报错

decltype的结果类型和表达式密切相关,如果对变量名加上括号,那么得到的将是该变量类型的引用

int i = 10;
decltype(i) a;	//a是一个int型变量
decltype((i)) b;	// 错误,b是一个整型引用,必须初始化

你可能感兴趣的:(C++面向对象编程,c++)