C++基础运算与数据结构


一、默认值形参与位域

默认值形参
有默认值的形参必须在形参列表最后,
调用时未给实参则按采用默认值,未给全则按左至右优先
定义及多个声明中只能定义一次默认值

位域
将类中多个数据成员打包,使不同成员共享相同字节
仅bool,char,int,enum类型的成员能被定义为位域
节省内存空间,增加运行时间
数据类型说明符 成员名:二进制位数;
unsigned number:27;

二、存储类型

auto:堆栈,暂时性存储,存储空间可呗若干变量多次覆盖使用
registger:存储在通用寄存器
extern:所有函数和程序段都可引用
stastic:以固定地址存放,整个程序运行期间都有效

三、生存期

1、静态生存期

对象的生存期与程序运行期相同,则具有全局寿命,
函数内部局部作用域中声明具有静态生存期的对象要用static,局部可见,只第一次进入函数时被初始化

2、动态生存期

局部作用域中声明的具动态生存期的对象,诞生于声明点,结束于声明所在块执行完毕时,每次进入函数都初始化

四、Setiosflags、setprecision操作符

#include <iomanip>

对齐方式
左对齐:ios_base::left
右对齐:ios_base::right
cout << setiosflags(ios_base::left) << setw(8) << name
以1位有效数字显示浮点数
cout << setw(8)<< setprecision(1) << value

五、逗号表达式

a=1+1,2+2;
先解1+1,再解2+2
结果为2+2

六、关系运算优先级

关系运算优先级
较高:< <= > >=
较低:= !=

七、逻辑运算优先级

逻辑运算优先级
! && || (高-低)

(a == b) && (++c==1)
前面表达式不成立时不会执行后面表达式
||则相反

八、三目运算符

1 ? 2 : 3
1必须是bool型

九、数组

1、二维数组

二维数组:int a[3] [4];   总共12个元素,可当做34列看待,名字依次是
         a[0] [0]    a[0] [1]     a[0] [2]     a[0] [3]
         a[1] [0]    a[1] [1]     a[1] [2]     a[1] [3]
         a[2] [0]    a[2] [1]     a[2] [2]     a[2] [3]
         a[ i ] [ j ]表示第 i+1 行 j+i 列的元素
初始化:
int a[3] [4] = { 1,  2,  3,  4,  5,  6,  7,  8,  9,  10,  11,  12}; 
int a[3] [4] = {
                { 1,  2,  3,  4},  
                { 5,  6,  7,  8},
                { 9, 10, 11, 12}  }

2、对象数组

元素是对象
类名 数组名 [常量表达式];
通过这个对象,便可以访问到它的公有成员
数组名[下标表达式].成员名

	a[i].move(i, i + 10);

SavingsAccount a[] = {
	SavingsAccount(date, "hehe7", 0.015),
	SavingsAccount(date, "yaya2", 0.015)
	};

十、指针

数据类型 *标识符;

	int * p;   表示声明指针:出现在声明语句
	cout << *p;   输出p所指内容,表示访问指针所指对象的内容:出现在执行语句或声明语句的初始化表达式
	int &rf;   声明引用
	int *p = &b; 表示取对象的地址:给变量赋值时=右边或在执行语句中
可声明指向常量的指针  const int * p1 = &b; 
可声明指针类型常量  int * const p2 = &a; 指针本身的值不能改变
void类型的指针可存储任何类型的对象地址  void *pv;
 p[-i] 等价于 *(p-i)     
指针变量可与整数0比较,为0NULL表示空指针(不指向任何有效地址的指针)

1、指针数组

数据类型 *数组名[下标表达式]int * p[3];   
p[i][j] 等价于 *(p[i]+j) 
数组内容是new来的: 一个个释放
for (int i=0;i<n;i++)
{
    delete []pStrArray[i];
}
delete pStrArray;

2、指针型函数与函数指针

指针型函数
数据类型 *函数名(参数表){。。。 };

函数指针:专用于存放函数代码首地址的变量
数据类型 (*函数指针名)(参数表);
赋值:函数指针名 =函数名;

3、对象指针

存放对象地址的变量

类名 *对象指针名;

访问对象的成员:

对象指针名 ->成员名  等价  (*对象指针名).成员名

4、this指针

隐含于每个类的非静态成员函数中的特殊指针,用于指向正在被成员函数操作的对象
执行成员函数获取成员数据时 return x;对系统来说执行的是 return this->x;

class A
{
	int num;
public:
	void setnum(int num)
	{
		///这个时候你直接写num=num就会产生二义性而混淆,但你可以用this
		this->num = num;
	}
};

5、智能指针

将普通的指针封装为一个栈对象,以类模板方式实现,C++11废弃了auto_ptr新增以下3个

①unique_ptr

保证同一时间内只有一个智能指针可以指向该对象,避免资源泄露

unique_ptr < string > pu1(new string ("hello world"));
unique_ptr < string > pu2;
pu2 = pu1;    // #1 不允许(pu1的所有权会被剥夺)
unique_ptr < string >pu3; 
pu3 = unique_ptr < string > (new string ("You"));// #2 允许(右值是临时的,调用unique_ptr的构造函数创建的临
                                                 //时对象在其所有权让给pu3后就被销毁)

②shared_ptr

当两个对象相互使用一个shared_ptr成员变量指向对方,会造成循环引用,使引用计数失效,从而导致内存泄漏。
多个智能指针可以指向相同对象,该对象和其相关资源会在“最后一个引用被销毁”时候释放。采用引用计数,记录当前内存资源被多少个智能指针引用。通过make_shared函数或者通过构造函数传入普通指针,通过get函数获得普通指针。

成员函数:
use_count 返回引用计数的个数
unique 返回是否是独占所有权( use_count 为 1)
swap 交换两个 shared_ptr 对象(即交换所拥有的对象)
reset 放弃内部对象的所有权或拥有对象的变更, 会引起原有对象的引用计数的减少
get 返回内部对象(指针), 由于已经重载了()方法, 因此和直接使用对象是一样的.
shared_ptr<int> sp(new int(1));  等价sp.get()

③weak_ptr

不控制对象生命周期的智能指针,指向一个 shared_ptr 管理的对象. 进行该对象的内存管理的是那个强引用的shared_ptr, weak_ptr只是提供了对管理对象的一个访问手段。
只可以从一个 shared_ptr 或另一个 weak_ptr 对象构造, 它的构造和析构不会引起引用记数的增加或减少。解决shared_ptr相互引用时的死锁问题

class B; //声明
class A { public:shared_ptr<B> pb_; //改为weak_ptr <B>pb_就不会内存泄漏 };
class B { public:shared_ptr<A> pa_; };
int main() { shared_ptr <B> pb(new B());
shared_ptr<A> pa(new A());
pb-> pa_ = pa;
Pa-> pb_ = pb;   }

6、指向类的非静态成员的指针 与 指向类的静态成员的指针

指向类的非静态成员的指针

类型说明符 类名::*指针名;      声明指向数据成员的指针
	类型说明符 (类名::*指针名)(参数表);    声明指向函数成员的指针
对数据成员指针赋值:
	指针名 =& 类名::数据成员名;
访问数据成员:
	对象名.*类成员指针名   或   对象指针名->*类成员指针名   
对成员函数指针赋值:
	指针名 =& 类名::函数成员名;
调用成员函数:
	(对象名.*类成员指针名)(参数表)(对象指针名->*类成员指针名)(参数表)    

指向类的静态成员的指针:
对类的静态成员的访问不依赖于对象,可用普通指针指向和访问

十一、结构体

struct 结构体名称
{public: 】 可省略,未指定访问控制属性成员为公有类型        
	公有成员
protected:       	保护型成员
private:        私有成员
};

全为公有成员时赋初值

类型名 变量名={成员数据1初值,成员数据2初值,....};

十二、联合体

默认访问控制属性为公有。全部数据成员共享同一组内存单元
不能继承,不支持多态,可不声明名称,变量中成员同时只有一个有意义

union 【联合体名称】
{      公有成员
	protected:      保护型成员
	private:        私有成员     };

十三、动态内存分配

程序在运行过程中按实际申请适量内存,使用结束可释放

动态创建堆对象:
	new 数据类型(初始化参数列表);//把参数存入该空间

若内存申请成功,new运算返回一个指向新分配内存首地址的类型的指针,可通过此指针对堆对象访问。申请失败,会抛出异常 int *p = new int;

删除由new建立的对象,释放指针指向的内存空间:new建立的对象只能删除一次(delete后将指针置空,则再次delete不会出错)

delete 指针名;   若删除对象,该对象的析构函数将被调用
创建数组类型的对象:
	new 类型名 [数组长度(可是任何能得到正整数值的表达式)];
	删除:delete[] 指针名;   
多维数组:new 类型名T[数组1维长度][数组2维长度]。。。;

其中第1维可为任何能得到正整数值的表达式,其他各维必须是结果为正整数的常量表达式
若内存申请成功,new运算返回一个指向新分配内存首地址的类型的指针,但不是T类型指针,是指向T类型数组的指针。
float (*cp)[25][10];
cp = new float[10])[25][10]; cp是指向二维float型数组的指针

使用注意

  1. new 和delete都是内建的操作符,语言本身所固定了,无法重新定制,想要定制new和delete的行为,徒劳无功的行为。
  2. 动态分配失败,则返回一个空指针(NULL),表示发生了异常,堆资源不足,分配失败。
  3. 指针删除与堆空间释放。删除一个指针p(delete p;)实际意思是删除了p所指的目标(变量或对象等),释放了它所占的堆空间,而不是删除p本身(指针p本身并没有撤销,它自己仍然存在,该指针所占内存空间并未释放),释放堆空间后,p成了空指针。
  4. 内存泄漏(memory leak)和重复释放。new与delete 是配对使用的, delete只能释放堆空间。如果new返回的指针值丢失,则所分配的堆空间无法回收,称内存泄漏,同一空间重复释放也是危险的,因为该空间可能已另分配,所以必须妥善保存new返回的指针,以保证不发生内存泄漏,也必须保证不会重复释放堆内存空间。
  5. 动态分配的变量或对象的生命期。我们也称堆空间为自由空间(free store),但必须记住释放该对象所占堆空间,并只能释放一次,在函数内建立,而在函数外释放,往往会出错。
  6. 要访问new所开辟的结构体空间,无法直接通过变量名进行,只能通过赋值的指针进行访问。
    用new和delete可以动态开辟和撤销地址空间。在编程序时,若用完一个变量(一般是暂时存储的数据),下次需要再用,但却又想省去重新初始化的功夫,可以在每次开始使用时开辟一个空间,在用完后撤销它。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值