【七】C++一些新的关键字 -- new、delete、强制类型转换
2015-08-23 14:55
363 查看
目录
目录1动态内存分配
2命名空间
3强制类型转换
C方式的强制类型转换
C强制类型转换
static_cast强制类型转换
const_cast强制类型转换
当volatile关键字作用于常量
reinterpret_cast强制类型转换
dynamic_cast强制类型转换
1、动态内存分配
C++中的动态内存分配已经和C语言有了明显区别:C++中通过new关键字进行动态内存申请
C++中的动态内存申请是基于类型进行的
delete关键字用于内存释放
变量申请和释放:
Type* pointer = new Type; // …… delete pointer;
数组申请和释放:
Type* pointer = new Type ; // …… delete[] pointer;
new关键字与malloc函数的区别:
new关键字是C++的一部分,malloc是由C库提供的函数
new以具体类型为单位进行内存分配,malloc只能以字节为单位进行内存分配
new在申请单个类型变量时可进行初始化,malloc不具备内存初始化的特性
new对基本类型申请空间后默认初始化为0
对于类类型new和delete还负责构造函数和析构函数的调用
示例:
exp-1.cpp
#include <iostream> using namespace std; int main() { //申请数组,并默认初始化为0 int **p = new int*[10]; for(int i = 0; i < 10; i++) { cout << p[i] << '\t'; } cout << endl; //申请单个变量,并指定初始值 int *a = new int(5); cout << "*a = " << *a << endl; //申请单个变量,并默认初始化为0 double *d = new double; cout << "*d = " << *d << endl; delete [] p; delete a; delete d; return 0; }
运行结果:
2、命名空间
在C语言中只有一个全局作用域C语言中所有的全局标识符共享同一个作用域
标识符之间可能发生冲突
C++中提出了命名空间的概念
命名空间将全局作用域分成不同的部分
不同命名空间中的标识符可以同名而不会发生冲突
命名空间可以相互嵌套
全局作用域也叫默认命名空间
C++命名空间的定义:
namespace name { /* … */ }
C++命名空间的使用:
使用整个命名空间:using namespace name;
使用命名空间中的变量:using name::variable;
使用默认命名空间中的变量:::variable;
默认情况下可以直接使用默认命名空间中的所有标识符:variable;
示例:
exp-2.cpp
#include <iostream> using namespace std; namespace First { int i = 0; } namespace Second { int i = 10; namespace Internal { struct Student { const char *name; int age; }; } } int main() { using Second::Internal::Student; First::i = 5; Student stu; stu.name = "Tom"; stu.age = First::i + Second::i; cout << "Name:" << stu.name << "\n" << "Age:" << stu.age << endl; return 0; }
3、强制类型转换
C方式的强制类型转换:
( Type )( Expression )Type( Expression )
示例:
exp-3.cpp
#include <stdio.h> typedef void(PF) (int); struct Point { int x; int y; }; int main() { //定义一个整数 int v = 0x12345; //下面就开始乱来了!想怎么搞就怎么搞! PF *pf = (PF*)v; char c = char(v); //我都不知道我在写什么.... pf(c); Point *p = (Point*)v; printf("Point::x = %d\n", p->x); printf("Point::y = %d\n", p->y); return 0; }
上面的程序,编译能过,最多也就给个警告,但是运行肯定出错!
C方式强制类型转换存在的问题
过于粗暴
任意类型之间都可以进行转换,编译器很难判断其正确性
难于定位
在源码中无法快速定位所有使用强制类型转换的语句
如何进行更加安全可靠的转换呢?
C++强制类型转换
C++将强制类型转换分为4种不同的类型static_cast强制类型转换
用于任何具有明确定义的类型之间的转换,只要不包含底层const,都可以使用!const char *cp = “C++”; char *q = static_cast< char* >(cp);
上面这句就是错误的,static_cast不能去掉底层const
用于基本类型间的转换,但不能用于基本类型指针间的转换!
用于有继承关系类对象之间的转换和类指针之间的转换!
Tip:
static_cast是编译期进行转换的,无法在运行时检测类型,所以类类型之间的转换可能存在风险。
示例:
exp-4.cpp
#include <iostream> using namespace std; int main() { int i = 97; char c; c = static_cast<char>(i); //OK! i = static_cast<int>(c); //OK! char *pa = static_cast<char*>(&i); ////Error!! cout << "char c = '" << c << "'"<<endl; cout << "int i = " << i <<endl; const char *cp = "C++"; char *q = static_cast< char* >(cp); //Error!! return 0; }
const_cast强制类型转换
用于去除变量的const属性!只能改变运算对象的底层const!
示例:
exp-5.cpp
#include <stdio.h> int main() { //这样声明,相当于得到了一个只读变量,而非常量 const int& j = 1; //相当于: int temp = 1; const int&j = temp; //temp来自符号表 int& k = const_cast<int&>(j); //对j这个只读变量取引用,并强制去掉了它的const属性:const int* const ==> int* const,得到了一个别名为k的普通变量 k = 5; printf("k = %d\n", k); //普通变量,来自存储空间 printf("j = %d\n", j); //只读变量,来自存储空间 printf("&k = %p\n", &k); printf("&j = %p\n", &j); //这里才是声明了一个常量,符号表中会有它 const int x = 2; int& y = const_cast<int&>(x); //这里对x这个常量取了引用,引用的本质是指针常量,所以导致编译器为常量x分配了存储空间 //然后,这里的const_cast相当于转换了:const int* const类型的指针为int *const类型 //而且,这里不能这些做:int& y = x; 会报错!!因为如果没有const_cast<int&>(x);那么x始终都还是一个常量,没有存储空间,不是只读变量! y = 8; printf("x = %d\n", x); //这里用的是常量,来自符号表 printf("y = %d\n", y); //这里用的是只读变量,来自存储空间 printf("&x = %p\n", &x); printf("&y = %p\n", &y); return 0; }
运行结果:
Tip:
关于以上程序运行结果的本质原因,在前面的文章中说过,请看这里!
当volatile关键字作用于“常量”
volatile关键字,告诉编译器不做任何的优化,每次直接到内存中存取值!volatile关键字的详细介绍,请看这里!
思考?
经过volatile关键字后,const int i = 1; 还是一个常量么?
验证方法:
我们取i的地址并去掉它的底层const属性,假设它还是一个常量,那么通过指针修改i的内存值后,i的输出值不会改变,因为常量的值来自于符号表;如果值改变了,说明i已经成为了一个只读变量,它的值来自于存储空间!
示例:
exp-6.cpp
#include <stdio.h> int main() { volatile const int i = 1; int *p = const_cast<int*>(i); *p = 100; printf("i = %d\n", i); printf("*p = %d\n", *p); return 0; }
运行结果:
Tip:
从结果上表明,volatile 关键字作用于常量时,常量会变成只读变量,不再使用符号表,而直接使用编译器为“常量”分配的内存空间中的值!
reinterpret_cast强制类型转换
用于指针类型间的强制转换用于整数和指针类型间的强制转换
通常为运算对象的位模式提供较低层次上的重新解释,直接复制二进制位来实现类型转换,是一种极其不安全的转换!
示例:
exp-6.cpp
#include <stdio.h> int main() { int i = 0; char c = 'c'; int* pi = &i; char* pc = &c; pc = reinterpret_cast<char*>(pi); pi = reinterpret_cast<int*>(pc); pi = reinterpret_cast<int*>(i); c = reinterpret_cast<char>(i); // Error! return 0; }
dynamic_cast强制类型转换
主要用于类层次间的转换,还可以用于类之间的交叉转换dynamic_cast具有类型检查的功能,比static_cast更安全
相关文章推荐
- 黑马程序员——C语言内存管理
- C语言 位操作
- 2016阿里巴巴c/c++研发工程师在线笔试题(附加题)(题目写的很乱,纯属碎片)
- 2016届 阿里巴巴校招研发工程师C/C++笔试题--2015.08.23
- 队列 c语言实现
- 2016阿里巴巴c/c++研发工程师在线笔试题(选择题)
- 如何在VC++中使用Windows Forms (VS2012-VS2015)
- 【C语言经典实例】-switch分支结构-模拟自动售货机
- 阿里巴巴2016校招在线笔试附加题(C++研发)
- hdu4762Cut the Cake(概率+大数操作(java)+C++高精度模板)
- C++实现九宫格游戏人机对战
- C语言编程中的问题
- Effective C++ 条款16 成对使用new和delete时要采取相同形式
- C语言中的atan和atan2
- 学习了C语言有很多感悟!
- Visual C++与Windows程序设计
- C语言选择菜单的试手程序!
- 运算符的优先级和结合性
- C++中GB2312字符串和UTF-8之间的转换 从CString 的转换
- C语言基础知识之(四):C语言中涉及的数字问题