一,名字空间:namespace
在C++中支持域:全局域,局部域,块域,名字空间域和类域.
1,名字空间的使用
名字空间域是随标准C++而引入的。它相当于一个更加灵活的文件域,使用花括号将文件一部分括起来,并使用关键字namespace开头给它起一个名字:
namespace lkq
{
int a1;
int a2;
int my_add(int a, int b) {
return a + b;
}
}
花括号括起来的部分称生命块。生命块中可以包括:类,变量(初始化),函数(带定义)。
最外层的名字空间称为全局名字空间域,即文件域。
名字空间域的引入,主要是为了解决全局名字空间污染问题,也就是防止程序中全局变量实体名和其他程序中全局变量实体名命名冲突。
//1,普通的命名空间
namespace lkq
{
int a = 10;
int b = 20;
int add(int a, int b) {
return a + b;
}
}
//2,名字空间域可分层嵌套,同样有分层屏蔽左右
namespace lkq
{
int a = 10;
namespace lkq{
int a = 10;
}
}
//同一个工程允许多个相同名称的命名空间
//编译器在最后会合成到同一个命名空间中
一个名字空间就定义了一个新的作用域,命名空间的所以内容都局限于该空间中。
2,名字空间的使用
1,加名字空间及作用域限定符
namespace lkq
{
int a1;
int a2;
int my_add(int a, int b) {
return a + b;
}
}
int main()
{
int a = 10, b = 20;
printf("%d", lkq::my_add(a, b));
return 0;
}
2,使用using将名字空间中成员引入
使用using声明可只写一次限定修饰名。using声明以关键字using开头,后面是被限定修饰的名字空间成员名:
using namespace lkq::add;
namespace lkq
{
int a = 10;
int b = 20;
int add(int a, int b)
{
return a + b;
}
}
int main()
{
int c = 10;
int n = 20;
printf("%d\n",add(c,n) );
}
二,new / delete
运行程序时,虚拟地址空间
内核:操作系统
栈区:函数的形参,非静态的局部变量,函数现场保护数据等等,栈是向下增长的。
共享库的内存映射区域:用于装在一个共享的动态内存库。用户可使用系统接口创建共享内存,做线程通信。
堆区:用于程序运行时动态内存分配,堆是可以向上增长的。
数据区:存储全局数据和静态数据,分为.bss和.data。
代码段:可执行的程序和常量数据。
c的动态内存管理:
c++的动态内存管理:
1,new运算符的使用
2,new的函数方法使用
3,定位new
4,new和malloc的区别
1,new是c++的运算符,malloc是函数
2,malloc申请空间需要手动计算大小,new自动计算大小
3,malloc申请空间时不会初始化,new可以初始化
4,malloc的返回值是void*,接收时需要强转,new不需要
5,malloc申请内存空间失败时返回NULL,使用时必须判空
new申请内存空间失败抛出异常,所以要有捕获异常状态程序。
5,从汇编来看new
int main()
{
int* pa=new int;
return 0;
}
在调试模式下转到反汇编,观察对应的汇编语言:
这里我们看到,我们调用了new运算符。而编译器在转换的时候调用了一个函数:opreator new的一
个函数,而这个函数恰恰就是new的底层实现。
我们来看一看operator new函数的源代码实现:
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{ // try to allocate size bytes
void *p;
while ((p = malloc(size)) == 0)
if (_callnewh(size) == 0)
{ // report no memory
static const std::bad_alloc nomem;
_RAISE(nomem);
}
return (p);
}
从这份源代码可以看出,operator new函数本质也是封装了malloc的函数,并且当申请内存空间失
败的时候不再是返回NULL,而是抛出异常。可以这么简单认为,operator new函数就是失败抛出
异常的malloc。