1.动态内存管理
(1)malloc和free
原型:
void* malloc(size_t size);
void free(void *ptr);
char *p =(char *)malloc(100 * sizeof(char));
free(p);
(2)new和delete
new/new[] 用法
函数原型:
void *operator new(std::size_t)throw(std::bad_alloc);
//开辟单地址空间
int *p = new int; //开辟大小为sizeof(int)空间
int *q = new int(3); //开辟大小为sizeof(int)的空间,并初始化为3。
//开辟数组空间
int *r = new int[3];
for(int i=0; i<3; i++)
r[i] = i;
int *a = new int[100]{0};//开辟大小为100的整型数组空间,并初始化为0。
//二维
int (*a)[6] = new int[5][6];
delete/delete[] 用法
函数原型:
void operator delete(void*)throw();
//释放单个int空间
int *a = new int;
delete a;
//释放int数组空间
int *b = new int[5];
delete []b; //数组要加一个[]
(3)两者的区别
1.属性
new是关键字(编译器支持),malloc是库函数(头文件支持)。
2.参数
new无需指定大小,malloc需要指定大小。
3.返回类型
new返回类型是对象指针,malloc返回的是void *
4.对于自定义的类
new会调用构造和析构函数,malloc不会调用构造和析构函数
5.分配失败
new会抛出异常,malloc返回空
6.内存泄露
两者都能检测到,new可以检查到哪一行,malloc不可以。
7.重载
C++允许重载new/delete操作符,特别的,布局new的就不需要为对象分配内存,
而是指定了一个地址作为内存起始区域,
new在这段内存上为对象调用构造函数完成初始化工作,
并返回此地址。而malloc不允许重载。
2.命名空间
命名空间是ANSIC++引入的可以由用户命名的作用域,用来处理程序中 常见的同名冲突。
关键字:namespace
//先定义一个命名空间
namespace user
{
char name[10];
int age;
}
int main()
{
user::age = 20; //(命名空间名称::变量名) 使用
printf("%d", user::age);
return 0;
}
一般三种方法使用:
(1)命名空间名称::变量名 (每次都必须这样写)
(2)声明 using namespace 空间名; 可以直接使用 变量名 (不推荐)失去意义
(3)声明 using 命名空间名称::变量名; 可以直接使用 变量名
3.模块化编程
防止头文件被重复包含造成类被重复定义
#ifndef _HEADERNAME_H
#define _HEADERNAME_H
(头文件内容)
#endif
4.assert断言机制原理以及使用
assert宏的原型定义在< assert.h>中,其作用是如果它的条件返回错误,则终止程序执行,
原型定义:#include < assert.h> void assert( int expression );
assert()宏的作用是现计算表达式 expression ,如果其值为假(即为0),
那么它先向stderr打印一条出错信息,
作用:在函数开始处检验传入参数的合法性
每个assert只检验一个条件,若同时检验多个条件时,如果断言失败,无法直观的判断是哪个条件失败
5.异常捕获和处理
关键字:
try:这个区段中包含了可能发生异常的代码,在发生了异常之后,需要通过throw抛出异常。
throw:throw 用于抛出异常,被抛出的异常可以是C++的内置类型(例如: throw int(1);),也可以是自定义类型。
catch:每个catch子句都代表着一种异常的处理。catch子句用于处理特定类型的异常。
语法:
try
{
被检查语句
throw 异常
}
catch(异常类型1)
{
进行异常处理的语句1
}
catch(异常类型2)
{
进行异常处理的语句2
}
6.副本构造器
副本构造器在如下情况会被自动调用:
1.当某个函数的返回值的类型是某个类的时候,该函数将创建一个该类对象的副本并把后者返回给自己的调用者。
2.当某个输入参数的类型是某个类的时候,系统将为该输入参数创建一个副本并将其传递到函数里去
3.当用户使用某个对象去初始化另一个对象时。
副本构造器和赋值操作符:
副本构造器形式为:MyClass(const MyClass &rhs); ,没有返回类型。
赋值操作符形式为:MyClass &operator=(const MyClass &rhs);
只要声明了一个有指针属性并将在析构器里释放那块内存的类,就需要实现一个副本构造器和一个赋值操作符,两者缺一不可。
一定要保证副本构造器对所有的属性(而不仅仅是指针)都进行了复制
7.强制类型转换
C++中高级强制类型转换操作符:
const_cast<MyClass*>(value):用来改变 value 的常量性;
dynamic_cast<MyClass*>(value):动态对象强制类型转换;
reinterpret_cast<T>(value):在不进行任何实质性转换的情况下,把一种类型的指针解释为另一种类型的指针或是把一种整数解释为另一种整数;
static_cast<T>(value):用来进行强制类型转换而不做任何运行时检查,老式强制类型转换的替代品
动态对象强制类型转换:
dynamic_cast<MyClass*>(value):用来把一种类型的对象指针安全地强制转换为另一种类型的对象指针;
如果 value 的类型不是一个 MyClass 类(或 MyClass 的子类)的指针,这个操作符将返回NULL。