C++基础学习笔记----第五课(动态内存分配、命名空间、强制类型转换)(一)

2014-11-24 02:59:09 · 作者: · 浏览: 7

本节主要讲了动态内存分配new和delete关键字的使用方法以及和malloc的差别,命名空间主要讲了命名空间的使用法和C++支持的四种强制类型转换。

C++中的动态内存分配

基本概念和使用方法

C语言中,malloc和free是C库提供的函数,其实它并不属于C语言的本身(毕竟是函数嘛),在C++中一样可以得到支持,但是C++中申请动态内存(new)和释放动态内存(delete)使用的是两个关键字,这两个关键是C++关键字。

无论是malloc和free函数还是new和delete关键字都是在堆上面获取内存空间的,也就是服从堆分配。

new关键字的使用方法主要包括两个方面:

①申请变量:Type* pointer = new Type;这里是创造一个指针,让这个指针指向新申请的一个Type

②申请数组:Type* pointer = new Type[N];这里创造一个指针,让这个指针指向一个新的申请的数组,这个数组有N个元素。

单个变量的申请和数组的申请是有差别的,数组的申请要注意我们准备申请的数组的大小。

释放内存也同时有两种情况:

①delete pointer 释放单个变量的内存

②delete[] pointer释放数组的内存

注意:在释放数组的时候必须加上[],否则编译器会认为释放的是一个变量的内存,造成内存泄露。例程如下:

#include 
  
   
int main()
{
	int *p = new int;
	*p = 2;
	*p = *p + 3;
	printf ("p = %p\n",p);
	printf ("*p = %d\n",*p);
	delete p;

	p = new int[10];
	for (int i = 0; i < 10; i++)
	{
		p[i] = i;
		printf ("p[%d] = %d\n",i, p[i]);
	}
	delete []p;
}
  
注意:这里的p是通过int *p = new int建立的指针,所以在释放之后可以直接建立指向10个int类型的数组,不需要再通知类型。p = new int[10]

下面的程序编译不会通过,编译器提示p重复定义,多次初始化

#include 
  
   
int main()
{
	int *p = new int;
	*p = 2;
	*p = *p + 3;
	printf ("p = %p\n",p);
	printf ("*p = %d\n",*p);
	delete p;

	int *p = new int[10];
	for (int i = 0; i < 10; i++)
	{
		p[i] = i;
		printf ("p[%d] = %d\n",i, p[i]);
	}
	delete []p;
}
  

new关键字和malloc函数的差别

①new关键字是C++的一部分,malloc是由C库提供的。

②new关键字能够以具体类型为单位进行内存分配,malloc只能够按照字节数进行内存分配。

③new在申请单个类型变量时可以进行初始化,malloc不能够进行初始化。

new关键字在申请单个变量时可以进行初始化的例程如下:

#include 
  
   
int main()
{
	int *pa = new int(1);
	char *pb = new char ('c');
	float *pc = new float(3.4f);

	printf ("*pa = %d\n", *pa);
	printf ("*pb = %c\n", *pb);
	printf ("*pb = %f\n", *pc);

	printf ("*pa = %d\n", *pa);
	delete pa;
	delete pb;
	delete pc;
}
  
同时不要忘记内存的初始化问题,或者哪一块内存是合法的,尽管是在C++中。下面的程序会发生崩溃。

#include 
  
   
int main()
{
	int *pa = new int(1);


	printf ("*pa = %d\n", *pa);

	pa = pa + 4;

	printf ("*pa = %d\n", *pa);
	delete pa;

}
  

C++中的命名空间

命名空间的使用背景

在C语言中只有一个全局作用域,也就是我们定义的变量在程序运行的始末都可以进行调用,其他有固定的使用范围的变量都是在子函数中之类的。但是这样可能导致我们的变量或者其他标示符造成冲突,尤其是在比较大的程序中。

在C++中的命名空间有效的解决了上述问题,命名空间将全局作用域分为不同的部分不同空间中的标示符可以同名而不会发生冲突命名空间可以相互嵌套全局作用域也叫默认命名空间。命名空间一定要定义在函数的外部,因为它本身就已经有效的控制了程序中变量的作用域,如果把它放在函数的内部,那么双重限制会导致程序发生混乱。

基本例程:

#include 
  
   

namespace first
{
	int i = 0;
}

namespace second
{
	int i = 1;
	namespace t
	{
		struct P
		{
			int a;
			int b;
		};
	}
}

int main()
{
	printf ("1");
	return 1;
}
  

命名空间的使用方法

①using namespace name 使用整个命名空间。

②using name::variable 使用命名空间中的某一个变量(即使这个命名空间没有被完全打开,我们仍然可以通过这种方式来使用这个空间中的某个变量)

③::variable 使用默认命名空间中的变量,

④在默认情况下,可以直接使用命名空间中的所有标示符。

例程如下:

#include 
  
   

namespace first
{
	int i = 0;
}

namespace second
{
	int i = 1;
	namespace t
	{
		struct P
		{
			int a;
			int b;
		};
	}
}

int main()
{
	using namespace first;
	using second::t::P;

	P p = {2,3};

	printf ("%d",i);
	printf ("%d",second::i);
	printf ("%d",p.a);
}
  
在上述程序中,我们只打开了一部分second的空间,所以这里如果要使用second中的i,我们仍然要声明second::i,但是这里的P已经完全打开,所以可以直接使用P命名空间在大型的C++项目中意义巨大。

如果仅仅打开第一层命名空间,即使在程序的运行过程中再通过第一层命名空间去访问第二层命名空间也是无法实现的。例程如下:

#include 
  
   

namespace first
{
	int b = 0;
	namespace first
	{
		int i = 5;
	}
}

int main()
{
	using namespace first;

	printf ("%d",first::first::i);
}

  

命名空间的使用注意事项

1.命名空间在嵌套的时候可以使用相同的名字,不过在打开命名空间的时候要按照顺序打开,同时作用域也是不相同的。例程如下:

#include 
  
   

namespace first
{
	int i = 0;
	namespace first
	{
		int i = 5;
	}
}

int main()
{
	using namespace first::first;
	
	printf ("%d",first::i);
}
  
上述程序的编译结果是0,这里可以这样理解,我们 通过using namespace first::first打开了名字为first和first