C++基础
第2章 变量和基本类型
2.2变量
2.2.4变量的作用域
当使用一个变量时候再去定义它,就在使用它的附近定义
局部变量与全局变量同名,程序引用时会引用局部变量,用全局变量需用在变量之前用“::”声明
2.3复合类型
2.3.1引用(别名)(reference)
引用定义时必须被初始化(类里的除外,且常引用“const引用”可以用任意表达式初始化),且一旦绑定(初始化)将无法修改绑定的对象
引用的定义:定义ir、jr: int &ir = I, &jr = j;
2.3.2 指针
定义指针暂时不使用时,指向空,C++空指针为:int *p = nullptr;
定义指针一定要初始化,指针如果定义时没有初始化,那么它指向了一个不确定的值,代码对它进行了某些操作,编译时编译器不会报错,如果运行时随即指向的随机地址也能用,那么运行时也不报错,这个最危险!!了。
int *ptr; //野指针!ptr 没有初始化,指向了一块随机地址
*ptr = 1;//可以在ptr指向的位置赋值,编译不报错!
cout << "*ptr = " << *ptr << endl; //运行结果显示 *ptr = 1, 运行时也没报错!
//有的编译器会告诉你使用了未初始化的指针
int *ptr1 = nullptr;//ptr 初始化为空
//*ptr1 = 1; //对空位置赋值,不起作用的,能编译,
//cout << "*ptr = " << *ptr << endl; //程序会异常退出
int a = 1;
ptr1 = &a; //对给ptr1重新赋值a的地址
cout << "*ptr = " << *ptr << endl;//这会就可以运行想要的结果了
不能直接操作void *指针所指的对象,因为不知道该对象的类型,也就无法确定能是用什么操作
可以定义指向指针的引用,但不能定义指向引用的指针(因为引用本身不是对象,只是别人的一个别名)。
2.4 const 限定符
const对象一旦创建必须初始化
const对象仅在文件内有效,不同文件有同名的const对象时,其实是不同的对象,若想要不同文件共享const对象,要在前面加extern修饰符:定义extern const int bufsize = fcn(); 其他文件声明:extern const int bufsize;
2.4.1 const的引用
const引用允许使用任意表达式初始化(const int i = 32; const int I = a * 2;)
引用const变量时必须使用const引用;不是const变量也可以使用const引用
const对象可以用别的类型的变量赋值,但是引用并未绑定该类型,而是绑定了中间变量,所以这样做不是想要的
2.4.2 const 指针
指向常量的指针,指针地址可以改,但是指针值不能改(const int pi = 3; const int *p = π)
常指针(指针是常量),指针地址不能改变,指针值指向的值可以改变(前提是指向的值不能使常量):(int a = 10; int *const p = &a; *p = 100;)
常对象指针(int *const p)、对象常指针(const int *p)的分别要点:const修饰的是谁
2.4.3 顶层const
2.4.4 constexpr 和常量表达式
常量表达式:值不会改变并且编译过程就能得到计算结果的表达式
一个对象或者表达式是不是常量表达式由它的数据类型和初始值共同决定
C++ 允许将变量声明为constexpr类型,以便由编译器来验证变量的值是否是一个常量表达式(constexpr int mf = 20; constexpr int limit = mf +1;)
字面值类型:类型一般,值也显而易见的称为“字面值类型”(算数类型、引用和指针都是字面值类型,类等不是字面值类型)
Constexpr指针初始值必须是nullptr或者0,或存储于某个固定地址中的对象(定义在函数体之外的对象其地址不变)
2.5 处理类型
2.5.1 类型别名
类型别名:类型的别名,使用时可以替换类型的原名
typedef: typedef double db, p; //db是double的别名,p是double 的别名;
Using: using db = double; //db是double的同义词
2.5.2 auto类型说明符
auto让编译器通过初始值来推算变量的类型,auto定义的变量必须有初始值(auto a = b + c //由b + c 的结果去推断a的类型)
auto赋值时,会忽略掉初始值的顶层const特性,const int c = 2; auto b = c;//b是int类型的,而不是const int类型的。
2.5.3 decltype类型指示符
Decltype 用以返回一个表达式的类型,并用来作为定义一个变量的类型(decltype(f()) a = x; //定义a为decltype类型的,用x去初始化)
特别:decltype处理一个引用类型时,decltype自身也是引用了,所以定义变量必须被初始化,除此之外,引用都是指其所绑定的对象。
*p是一个解引用操作,所以decltype(*p)得到一个引用类型,用其定义变量是引用类型且必须初始化。
Decltype的表达式如果是加上括号的变量,得到的结果将是引用(decltyoe((i))d = i; //d 是一个i类型的引用,必须被初始化,decltype 多套几层()也都一样是引用类型)
Decltype 里面的表达式不会运行
赋值表达式会产生引用类型,用之初始化decltype时,decltype定义的变量是引用,必须初始化。
int a = 10;
int b = 20;
decltype(a = 20)d = a;
cout << "d = " << d << endl;
cout << "a = " << a << endl;
2.6自定义数据结构
数据结构:是把一组相关的数据元素组织起来、并提供函数、运算的策略和方法
类应当被定义在头文件内,且头文件的名字应当与类名相同
预处理器概述
#define 指令将一个名字设定为预处理变量,用#undef 取消预定义
#define 和 #undef无视代码块{},跨代码块使用,在一个代码块中定义的东西可以在v另一个代码块中使用或取消预定义
#ifdef:当且仅当变量为已定义时为真,遇到#endif结束
#ifndef:当且仅当卞良圩未定义时为真,遇到#endif结束
#include
using namespace std;
#ifndef HEAD_FILE_H //如果之前没有定义过HEAD_FILE_H,那么执行以下语句
#define HEAD_FILE_H //将判定里面的实现
#include
struct GoodMorning {
int i = 0;
};
#define YES 1
#endif // !HEAD_FILE_H 预处理到endif 结束
int main()
{
cout << "hello world " << YES << endl;
getchar();
}