cpp中:
-
0开头的整数表示8进制
-
0x或者0X开头的表示16进制
//cpp中如果两个字符串位置紧临并且仅仅由这些空白字符组成的时候实际上表示的是一个整体 因为写在一行内不合适
cout << "wat aputopau wp upa "
"hahah hah ah";
常用的转义符号如下:这些转义符号被当成一个字符而不是占两个字符
符号 | 意思 |
---|---|
\n | 换行符 |
\t \v | 横向制表符 纵向制表符 |
\a | 报警符号 |
\\ | 反斜线 |
? | 问号 |
\" ’ | 双引号 单引号 |
\r | 回车符 |
\b | 退格符 |
\f | 进纸符 |
指定字面值的类型 可以参照pdf63页
L'a'; //wchar_t
u8"hi"; //utf-8 用8位编码来编码
42ULL; //unsigned long long
1E-3F; //long double
/*这里可以简单的看出来前缀一般指定编码格式而后缀一般指定类型*/
声明一个变量在其前面加extern 变量只能被定义一次但是可以被多次声明
extern int i;//声明但是没有定义i
int i;//声明并且定义了i这个变量
extern int i =1;//这种显式的声明也是定义的一种
cpp的标识符由字符、数字和下划线组成并且必须以字母或者下划线开头
一些特殊的标识符
alignas(结构体中用于字节对齐心) | friend | register(请求把变量存储到编译器中) | true | alignof(判段对齐位数) | |
---|---|---|---|---|---|
decltype | |||||
friend | 友元函数 | register | 请求把变量存储到寄存器中register int a; |
关键字 | 类型 |
---|---|
alignas | 用于自定义类型控制内存对齐位数 struct alignas(8) Student{};alignas(char)=1 |
alignof | 用来得到这种变量在内存中的对齐字节数 |
asm | 用于嵌入汇编,现在还没有必要了解 |
auto | 根据初始表达式来自动推断类型:auto f=3.14; auto it=vect.begin();auto ptr=[](double x){return x**2} |
try catch throw | try {throw ExceptionName}catch(ExceptionName e1){} catch(ExceptionName2 e2){} |
char char16_t char_32_t w_char | |
constexpr | 指定的返回值和参数必须是字面值 |
const_cast | 转换运算符可以去掉const限定的内容 |
decltype | 返回操作数的类型decltype(i) j; |
default | 用于switch当所有都没有匹配的时候就会进入这个匹配 |
dynamic_cast | 主要用于将基类的指针或引用安全地转换成派生类的指针或引用 |
explicit | 禁止单参数构造函数"被用于自动型别转换,其中比较典型的例子就是容器类型。在这种类型的构造函数中你可以将初始长度作为参数传递给构造函数。 |
export | 为了访问其他编译单元(如另一代码文件)中的变量或对象,对普通类型(包括基本数据类、结构和类),可以利用关键字 extern,来使用这些变量或对象时;但是对模板类型,则必须在定义这些模板类对象和模板函数时,使用标准 C++ 新增加的关键字 export(导出)。 |
extern | 声明变量或函数为外部链接,即该变量或函数名在其它文件中可见。被其修饰的变量(外部变量)是静态分配空间的,即程序开始时分配,结束时释放。用其声明的变量或函数应该在别的文件或同一文件的其它地方定义(实现)。在文件内声明一个变量或函数默认为可被外部使用。在 C++ 中,还可用来指定使用另一语言进行链接,这时需要与特定的转换符一起使用。extern "C" 声明语句``extern "C" {声明语句块} |
friend | 声明友元关系,友元可以访问与其友friend关系的类中的private/protected成员。友元包括友元函数和友元类 |
inline | inline int(){} |
multable | 被multable修饰的变量将会处在永远可以改变的状态即使在const函数中也可以改变这个变量的值 |
namespace | 用来在逻辑上组织类,是一种比类大的数据结构 |
new | 用于新建一个对象,其运算符总是返回一个指针,这个指针由new创建 |
operator | 用于操作符重载 |
private | 访问控制符,被标记为private的字段只能在本类和友元中使用 |
protected | 访问控制符,只能在本类以及子类和友元中使用 |
public | 访问控制符,公开的,都可以使用 |
register | 告诉编译器想把这个放进寄存器中 |
reinterpret_cast | reinpreter_cast<type-id (expression) type-id应该是一个指针,引用,算数类型或者成员指针。可以把一个指针转换为一个整数也可以把 一个整数转成一个指针 |
static | 修饰静态变量或者静态函数,作用范围位这个文件,程序开始时分配空间结束时释放空间。c++中成员变量被声明位static,意味着被类的所有实例共享。并且类的静态成员函数也只能访问静态成员。类的静态成员变量一定要在声明它的文件范围内进行初始化才能使用。 |
static_cast | static_cast <type-id> (expression) 这个函数把expression类型转换为type-id类型,但是没有运行时检查来保证转换的安全性。 |
struct | 结构类型可以,cpp中可以实现面向对象程序设计 |
template | 模板,用这个来实现泛型 |
this | 返回调用者本身的指针 |
throw(一般和catch except搭配使用) | 可以用这个关键子抛出一个异常对象 |
typeid | 指出指针或者引用指向的对象的实际派生类型 |
typename | typename(类型名字)关键字告诉编译器把一个特殊的名字解释成一个类型。 |
uinon | 联合,类似于enum但是enum实际上是int类型的,union可以用于任何类型 |
using | using namespace:😗 |
virtual | 虚的,用来实现多态机制 |
volatile | 不稳定的,限定一个对象可以被外部进程改变 |
引用和指针:
指针应该处于一下的四个状态之内:
- 指向一个对象
- 指向紧临对象所占空间的下一个位置
- 空指针,意味着没有指向任何对象
- 无效指针,即不同于以上的几种状态
int *p = &temp;
int &q = *p;
//由上面可以看到在声明语句中之子很合引用用来组成复合类型,但是在表达式中角色又转变成运算符。
生成空指针的方法:
int *p1 = nullptr;
int *p2 = 0;
int *p3 = NULL;
引用不是对象但是指针是对象
const
const对象创建完成后就不能改变,需要初始化。其初始值可以使任意复杂的表达式。
const int i = func();
const int i = 42;
:const int i;
❌ 错误,一定要初始化
const对象只在文件内有效,当多个文件出现了同名的const变量时,等同于在不同文件中分别定义了独立的变量。
如果想只在一个文件中定义但是多个文件中调用const变量:在声明和定义都添加extern关键字,这样只要定义一次即可。
extern const int bufSize = fcn(); extern const int bufSize;
int i=42;
const int &r1=i; //允许将const int& 绑定到一个普通int对象上
const int &r2=42; //r1是一个常量引用
const int &r33=r1*2; //r2是一个常量引用 r1*2是一个常量表达式
int &r4 = r1*2; //错误,右边是一个常量表达式,
//非常量引用不能绑定到临时量中:引用绑定到临时变量没什么意义,你都用非常量了肯定是想改变这个值,但是你改变一个临时的值有什么用呢
float pi = 3.14;
int &pi_p = pi; //因为类型不同编译器会生成中间临时变量,所以这次绑定是非法的。
指针和const
指向常量的指针不能改变其所指对象的值
想要存放常量对象的地址只能使用指向常量的指针
和变量一样可以使用一个指向常量的指针指向一个非常量的对象
指向是对象因此可以把指针定义为常量指针:
/*声明部分从右向左读,并且以*为分界点。*/
int errNumb=0;
int *const curErr = &errNumb;//curErr最近的是const 说明这个指针对象是一个常量对象,它所指向的类型是一个int类型。
const double pi = 3.14159;
const double *const pip = π//pip最近的是const说明它是一个常量对象,然后再前面是const double说明它指向一个常量型的双精度浮点数。
常量表达式是指值不会改变并且再编译过程就能得到计算结果的表达式
显然字面值(算数类型、引用和指针都是字面值,自定义的类、IO库、string等类型都不是)是常量表达式,用常量表达式初始化的const对象也是常量表达式。
常量表达式在编译的时候就进行计算。
const int max_files=20;
const int limit=max_files+1;
int staff_size=27; //这不是常量表达式因为没有使用const修饰
const int sz=get_size(); //不是,因为这个具体的值需要等到运行时决定。
/******使用constexpr来由编译器验证是不是常量表达式******/
constexpr int mf=20;
constexpr int limit=mf+1;
constexpr int sz=size(); //仅当size是一个constexpr函数时才是一条正确的声明语句
注意:constexpr的声明中如果定义了一个指针,限定符constexpr仅对指针有效,与指针所指的对象无关。如下:
const int *p=nullptr;//这里p是一个指向const int类型的指针
constexpr int *p=nullptr;//这里是p是一个指向int类型的const指针
顶层const和底层const
指针如果添加const修饰符有两种情况:
- 指向常量的指针。 代表不能改变其指向内容的指针。比方说
const int *a;
这种属于底层的const - 常量指针。
int * const p;
这种属于顶层的const
常量的底层const不能赋值给非常量的底层const:
int num = 3;
const int *p_a = #
int *p_b = p_a; //错误,不能把一个指向常量对象的指针赋值给一个非常量的底层
const int *p_c = p_a //这样就没问题 或者const int * const p_c = p_a都行
对常量对象取地址也是一种底层的const
const int a = 3;
auto p = &a; //这时候p是一个指向常量对象的指针,保持了底层的const
处理类型
类型别名
两种方式可以定义类型别名:
-
typedef double db;//这里db就是double类型的同义词
typedef wages base,*p//这里base是double类型的同义词,p是double *的同义词
-
using db=double;//
using f=int()(int,int);
auto类型
auto一般会忽略顶层const,把底层保留下来。如果希望推断出来的类型是一个顶层const需要明确的指出。
const int a = 0,&a_=a;
auto b = a; //这时候b就是一个int类型,忽略了顶层的const
auto p = &a; //这时候p是一个int *const 类型,保持了底层的const
auto q = a_; //这时候q也是一个int类型。
const auto b = a; //这时候b就是一个const int类型的。因为明确指出了const类型来修饰auto
decltype类型指示符
decltype用来推断出操作数的数据类型。在此过程中编译器分析表达式并得到它的类型却不实际计算它的值。
decltype(func()) sum = 10;//这里编译器只是分析这个函数的返回值而不计算这个函数
decltype处理顶层const和引用的方式和auto有些不同:如果decltype使用的表达式是一个变量,则decltype返回该变量类型的值(包括顶层const和引用在内)
const int ci = 0,&cj = ci;
decltype(ci) x = 0; // x的类型是const int
decltype(cj) z = 1; // z的类型是const int &,这里和auto对引用的推断有些区别。需要初始化。
int i=0,*p=&i,&r=i;
decltype(r) temp = 1; //temp是一个int&类型,需要初始化
decltype(cj+0) temp; //temp是一个int类型,不需要初始化
decltype(*p) temp = 1; //temp是一个int&类型,这和我们的认知一样(*p是一个解引用的操作其实得到的是一个指向i的引用),这里也需要初始化
2.6 自定义数据类型
类数据成员
类体定义类的成员,类中只有数据成员,其定义了类的对象的具体内容。
类的数据成员可以有一个类内初始值。
struct Sales_data{
string bookNo;
unsigned uints_sold=0; //数据成员的初始值
double revenue=0.0;
};