C++难点记录
预编译
-#line
-#error
加打印错误信息(不用加"")
-#proram
debug:调试版本,内有调试代码和库 release:发行版本,优化,紧凑
-
函数默认值
-
有声明写在声明,没声明写在定义
int a(int b=1);
-
第一个默认值参数后右边全部要加默认值
-
重载时如果前面相同参数而后面不同参数设置默认值会导致错误
-
-
typedef
-
定义数据类型,可以int等 也可以struct等
typedef int p
p a=10; -
分析方法:由变量名出发先右看,后左看,一个一个圆括号跳出
-
用于简化相同重复的复杂定义
-
类型不安全(指针的类型的强制转换)
-
联合
- 共用一段地址
- 一个成员被赋值时其他成员被重写
-
引用(reference)
- 不能建立数组的引用
- 可以用于传递给函数的数据较大时
- 在主调函数的调用点处,必须用变量的地址作为实参
- 不能返回局部变量
- 返回引用,需在函数名前加&,return处不用加& 接收的加不加都行
- 经常操作一个对象的操作符的重载的返回值
- 使用引用的时机。流操作符<<和>>、赋值操作符=的返回值、拷贝构造函数的参数、赋值操作符=的参数、其它情况都推荐使用引用。
- 作为成员变量不能赋值来初始化,要用初始化列表
sizeof是编译时运算符
-
指针
- 用指针创建的常量数组不能修改其数组成员的值
new delete
- 用指针创建的常量数组不能修改其数组成员的值
-
const
-
只能在定义的文件中使用,定义的对象不能修改其值,引用对象可以是不同但相关类型(E:int和float,其间会产生中间变量,实际是对该中间变量)
-
动态数组必须初始化
-
类必须提供默认构造函数
-
指向常量指针(指向const对象的指针),可以重新赋值,使指向其他const对象,必须初始化,
const double *cptr;//是cptr指向的对象为const,不是指针为const
-
const对象的地址不能给非const指针(void也适用)
-
非const对象的地址可以赋给const对象的指针,但不能通过const对象的指针修改该对象(他原先的指针可以修改自己)
-
常指针:指向const对象的const指针,指针的值不能改
double *const pi_ptr = ...;
-
指向常量的常指针
const *const pi_ptr = ...;
-
在类中不会修改数据成员的函数都应该声明为const即为常成员变量,编写时修改类数据成员,提高程序健壮性
类型说明符 函数名(参数列表) const;//声明和定义都要加const
-
只有常成员变量才能操作常量或常对象
-
函数的形参为const类型
-
const &a=b; 不能通过a的值修改地址下的值,但可以修改B
-
const成员变量初始化用初始化列表,不能用赋值
-
在内存中只有一个拷贝
-
const修饰指针为顶层指针,修饰所指对象为底层指针
-
const_cast 改变运算对象的底层const
int *p_f = const_cast<int *>(p_e)
-
类里的数据成员只能在构造函数中用列表初始化,在构造函数执行初始化完才赋予const属性
-
-
const_casr
- 属于强制类型转换
- 用于函数的形参非const,在不修改const变量值的前提下将const变量作为传参
- 用于指向const变量的指针指向了非const变量,无法通过该指针修改变量值的情况
-
define
- 在内存中有多份拷贝,比const占空间
- 无论在哪里定义都为全局
-
数组
- 数组作为函数的参数传递时,数组会退化为定义数组类型的指针,sizeof取得其类型的大小
- 数组名赋值给指针也会退化为数组类型的指针
- sizeof数组名 得到其大小数组数*类型
- 定义数组必然创建新空间
- 旧编译器不能用变量当下标定义,新的有些可以
extern
-extern conut 能在所有文件中使用,其他类型默认加了extern
-一个文件中定义,头文件中声明,多个文件使用
-声明在函数体中时不能被初始化
-相当于声明未解决符号表
volatile:编译器做优化会把变量值存放到别处访问,而该关键字使代码每次都从原地址访问
- 1). 并行设备的硬件寄存器(如:状态寄存器)
- 2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
- 3). 多线程应用中被几个任务共享的变量
-
mutable
- 用于被const修饰函数也可以修改非成员变量,需将该变量用mutable修饰(如const般)
-
枚举
- 枚举常量的序号默认从0
- 序号号指定值后依次加一,前的按默认排序,序号可重复
- 枚举产量只能以标识符形式,不能整数型字符型等
- 可进行关系运算、赋值、输出,都是以其序号为数据
指针
只能使用指向常量的指针来存放常量对象的地址
运算
-
判断执行顺序
-
优先级
-
结合顺序
C语言中具有右结合性的运算符包括所有单目运算符以及赋值运算符(=)和条件运算符。其它都是左结合性 结合性是在相同优先级时判断哪个运算符先执行
-
类 和 结构体
-
eplicit 使显式
class A{A(int a);A(float a)} A a = 20; //相当于给A的对应构造函数(A (int a))传入20,为隐式
-
初始化列表
-
基类有带参构造函数,派生类对其初始化不能用赋值
-
基类有数据成员,派生类对其初始化不能用赋值
-
对于数据密集型,比构造函数赋值更高效
-
还有这种用法:Point::Point(T a,T b):x(a),y(b){} x,y为成员变量
class A{
int a;
float b;
A():a(20),b(1.3);//初始化时进行赋值不能 a = 20;
}
-
-
拷贝构造函数
Class A { ... A(const A& C) } 构造函数的对象时该类的引用,用于 A a(20),b; a=b;
-
编译器的默认的拷贝构造函数的功能:给成员变量赋值,是浅拷贝
-
会拷贝对象,但不拷贝静态成员
-
浅拷贝对于动态量会出错(指针会对同一区域多次销毁导致错误)
-
深拷贝对于动态量进行new操作
-
用于复制对象产生新实例
-
用引用传递时防止递归
-
特殊的构造函数
-
当类定义的同时赋值会不执行构造函数而执行拷贝函数
当 一个对象需要以值方式传递时,编译器会生成代码调用它的拷贝构造函数以生成一个复本。如果类A的拷贝构造函数是以值方式传递一个类A对象作为参数的话,当 需要调用类A的拷贝构造函数时,需要以值方式传进一个A的对象作为实参; 而以值方式传递需要调用类A的拷贝构造函数;结果就是调用类A的拷贝构造函数导 致又一次调用类A的拷贝构造函数,这就是一个无限递归。
-
参数形式
a) X& b) const X& c) volatile X& d) const volatile X&
-
类中可以存在超过一个拷贝构造函数
注意,如果一个类中只存在一个参数为 X& 的拷贝构造函数,那么就不能使用const X或volatile X的对象实行拷贝初始化. 如果一个类中没有定义拷贝构造函数,那么编译器会自动产生一个默认的拷贝构造函数。 这个默认的参数可能为 X::X(const X&)或 X::X(X&),由编译器根据上下文决定选择哪一个。
-
必须重载运算符
-
永远要显式拷贝构造函数或operate=或=default
-
-
运算符重载
-
不可重载的运算符:
.成员访问运算符 .*和->*成员指针运算符 ::域运算符 sizeof长度运算符 ?:条件运算符 #:预处理符号
-
定义
xx operatorx (。。。); xx为返回值,x为运算符
运算符的优先级、结合性、操作数个数和语法结构保持不变
-
-
new
- 失败时有些编译器(按C++标准)会抛出【bad_alioc】异常不返回空指针,有些不会抛出异常而返回空指针,【new (std::nothorw) int 】则可以把抛出异常转为空指针
- set_new_handler(传入已经定义的错误处理函数) 来处理 在new之前设置
类
C++ 的类有四类特殊成员函数,它们分别是:默认构造函数、析构函数、拷贝构造函数以及拷贝赋值运算符。 没有定义时系统会自动隐式定义
=default会把自动生成的特殊成员函数显式
在函数后加上 =delete 相当于private ,析构函数不能加
-
析构函数
-
一般定义为虚函数
-
类销毁时调用
class A{~A()} -
固定delete[] 指针
-
-
友元
在类中对某个方法定义前加friend ,在类外定义可以使用该函数的私有,在使用其非静态变量时需用其对象
-
参数加const
表示常量,使this指针变为常指针常量
-
构造函数
- 基类有有参时,派生类必须对其初始化
- 定义为全局的对象的构造函数先于main执行
=default
结构体
-
“:”位域,规定数据占的比特数
struct A{ int b:2; int :3; / int c:3}
多态
动态绑定
- “指针->函数()”或“引用变量.函数()”的方式调用C++类中的虚函数才会执行
编译和运行的不同
-
virtual
-
虚函数
不一定被子类重写 在类中会产生4个字节存放虚函数表的地址
-
纯虚函数
纯虚函数的语法:将成员函数定义为virtual后面加上 = 0该函数没有函数体,调用时使用指针,即抽象函数,必须被子类重写
virtual <类型><函数名>(<参数表>) = 0;
有纯虚函数的类为接口(或抽象类) -
虚基类
:virtual public A; 继承的多个类的共同的父类,该父类只有一个对象;
-
-
inline 内联函数
-
不能包含循环函数!
编译时在使用的地方插入函数的代码,用于不复杂但使用频繁的函数
-
函数多语句用内联,单语句用define(可能)
-
switch
- 在4个以上时效率高于if,4个以下差不多
数据结构
-
10种排序
-
队列
- 循环队列
-
内模式
多个属性构成的一个实体的形式 内模式时最底层的,给出类数据库物理存储结构和存取方法
模板
其他
pragama pack(n)
设置对齐
上一篇: 洛谷P3952 时间复杂度
下一篇: 信息安全MD5加密