C++深度解析教程学习笔记(4)C++中的新成员
1. 动态内存分配
(1)C++通过 new 关键字进行动态内存申请,是以类型为单位来申请空间大小的
(2)delete 关键字用于内存释放

▲注意释放数组时要加[],否则只释放这个数组中的第 1 个元素。
C++中的动态内存分配
#include <stdio.h>
int main()
{
int* p = new int;
*p = ;
*p = *p + ;
printf("p = %p\n", p); //p 保存堆上开辟空间的地址
printf("*p = %d\n", *p);//
delete p;
p = new int[];//申请 10 个 int 型空间
for(int i=;i<; i++)
{
p[i] = i + ;
printf("p[%d] = %d\n", i, p[i]);
}
delete[] p; //注意:释放数组时[]不能漏掉
return ;
}
2. new 关键字
(1)对比 new 和 malloc
|
new |
malloc |
|
|
性质 |
是个关键字,属C++的一部分 |
是由C库提供的函数 |
|
申请单位 |
以具体类型为单位 |
以字节为单位 |
|
内存初始化 |
申请单个类型变量时可进行初始化 |
不具备内存初始化的特性 |
(2)new 关键字的初始化
int* pi = new int();
float* pf = new float(2.0f);
char* pc = new char('c');
初始化动态内存
#include <stdio.h> int main()
{
int* pi = new int(); //开辟1个int型空间,并初始化为1
//int* pa = new int[1];//注意,这时申请一个数组,与前一行含义不同 float* pf = new float(2.0f);
char* pc = new char('c'); printf("*pi = %d\n", *pi); //
printf("*pf = %f\n", *pf); //2.000000
printf("*pc = %c\n", *pc); //c delete pi;
delete pf;
delete pc; return ;
}
3. C++中的命名空间
C++中命名空间概念用于解决名称冲突问题
(1)在 C 语言中只有一个全局作用域
①C 语言中所有的全局标识符共享同一个作用域
②标识符之间可能发生冲突
(2)C++中提出了命名空间的概念
①命名空间将全局作用域分成不同的部分
②不同命名空间中的标识符可以同名而不会发生冲突
③命名空间可以相互嵌套
④全局作用域也叫默认命名空间
(3)C++命名空间的定义:namespace Name {}
①使用整个命名空间:using namespace name;
②使用命名空间中的变量:using name::variable;
③使用默认命名空间中的变量: ::variable
命名空间的使用
#include <stdio.h> namespace First
{
int i = ;
} namespace Second
{
int i = ; //命名空间的嵌套
namespace Internal
{
struct P
{
int x;
int y;
};
}
} int main()
{
using namespace First;//使用First整个命名空间
using Second::Internal::P;//使用命名空内部的P结构体 printf("Fisrt::i = %d\n", i); //0。可以直接写i,因为使用了First整个命名空间
printf("Second::i = %d\n", Second::i);//1。须带命名空间的名字 P p = {, }; printf("p.x = %d\n", p.x);//
printf("p.y = %d\n", p.y);// return ;
}
4.新型的类型转换
4.1. C 方式的强制类型转换
(1)转换形式
①(Type)(Expression)
②Type(Expression) //老式的
#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);//老式写法,很像函数调用
Point* p = (Point*)v; pf(); printf("p->x = %d\n", p->x);
printf("p->y = %d\n", p->y); return ;
}
(2)强制类型转换存在的问题
①过于粗暴:任意类型之间都可以进行转换,编译器很难判断其正确性
②难于定位:在源码中无法快速定位所有使用强制类型转换的语句
4.2. C++中新式的 4 种强制类型转换
(1)用法:xxx_cast(Type)(Expression)
(2)4 种类型
|
类型 |
适用范围 |
举例 |
备注 |
|
static_cast |
①基本类型之间 ②不能用于基本类型的指针之间 ③类与子类对象之间的转换或类指针间转换 |
int i = 0; char c = 'A'; int* pi = &i; char* pc = &c; c = static_cast<char>(i); //ok //不能用于基本类型的指针间转换 pc = static_cast<char*>(pi);//oops |
|
|
const_cast |
目标类型(即尖括号内的类型)必须是指针或引用 |
//i有内存,因别名,每次从内存读取i const int& i = 1;//i为引用 int& a = const_cast<int&>(i); const int j = 1; //为j分配内存,但不会去用它,从符号表中取j int& b = const_cast<int&>(j); a = 5; //i==5;a==5; b = 3; //j==1,b==3; |
用于去除变量的const属性 |
|
reinterpret_cast |
①用于指针类型间 ②用于整数和指针类型之间 |
typedef void PF(int); int i = 0; char c = 'c'; int* pi = reinterpret_cast<int*>(&c); char*pc = reinterpret_cast<char*>(&i); PF*pf= reinterpret_cast<PF*>(0x12345678); //以下错,要用static_cast c = reinterpret_cast<char>(i); |
reinterpret_cast直接从二进制位进行复制,是一种极其不安全的转换。 |
|
dynamic_cast |
①用于有继承关系的类指针间。②用于有交叉关系的类指针之间 |
详见后面章节的分析 |
①dynamic_cast具有类型检查的功能 ②需要虚函数的支持 |
#include <stdio.h> void static_cast_demo()
{
int i = 0x12345;
char c = 'c';
int* pi = &i;
char* pc = &c; c = static_cast<char>(i);//基本类型 //基本类型的指针间,非法
//pc = static_cast<char*>(pi);
} void const_cast_demo()
{ //用常量初始化引用,要分配内存。故j为变量,因加const而成只读变量
const int& j = ;//j为引用--》只读变量,说明j不能做为左值而己
int& k = const_cast<int&>(j); //转为普通引用,k就是j的别名 k = ; printf("k = %d\n", k); //
printf("j = %d\n", j); // const int x = ; //x为常量
int& y = const_cast<int&>(x);//此时,会为x分配内存
//int z = const_cast<int>(x); //oops,目标类型只能是引用或指针 y = ; printf("x = %d\n", x); //
printf("y = %d\n", y); //
printf("&x = %d\n", &x);
printf("&y = %d\n", &y); //x与y的内存地址是相同的
} void reinterpret_cast_demo()
{
int i = ;
char c = 'c';
int* pi = &i;
char* pc = &c; pc = reinterpret_cast<char*>(pi); //ok,指针间
pi = reinterpret_cast<int*>(pc); //ok,指针间
pi = reinterpret_cast<int*>(i); //ok,整数与指针间
//c = reinterpret_cast<char>(i); //oops,基本类型间转换,要用static_cast } void dynamic_cast_demo()
{
int i = ;
int* pi = &i;
char* pc = dynamic_cast<char*>(pi);//oops,目标类型应为类的指针或引用
} int main()
{
static_cast_demo();
const_cast_demo(); reinterpret_cast_demo();
dynamic_cast_demo();
return ;
}
新式类型转换以 C++关键字的方式出现
①编译器能够帮助检查潜在的问题
②非常方便的在代码中定位
③支持动态类型识别(dynamic_cast)
C++深度解析教程学习笔记(4)C++中的新成员的更多相关文章
- C++深度解析教程学习笔记(6)对象的构造和销毁
1. 对象的初始化 (1)从程序设计的角度看,对象只是变量,因此: ①在栈上创建对象时,成员变量初始化为随机值 ②在堆上创建对象时,成员变量初始化为随机值 ③在静态存储区创建对象时,成员变量初始化为 ...
- C++深度解析教程学习笔记(5)面向对象
1. 面向对象基本概念 (1)面向对象的意义在于 ①将日常生活中习惯的思维方式引入程序设计中 ②将需求中的概念直观的映射到解决方案中 ③以模块为中心构建可复用的软件系统 ④提高软件产品的可维护性和可扩 ...
- C++深度解析教程学习笔记(3)函数的扩展
1.内联函数 1.1.常量与宏的回顾 (1)C++中的 const 常量可以替代宏常数定义,如: ; //等价于 #define A 3 (2)C++中是否有解决方案,可以用来替代宏代码片段呢? 1. ...
- C++深度解析教程学习笔记(2)C++中的引用
1.C++中的引用 (1)变量名的回顾 ①变量是一段实际连续存储空间的别名,程序中通过变量来申请并命名存储空间 ②通过变量的名字可以使用存储空间.(变量的名字就是变量的值,&变量名是取地址操作 ...
- C++深度解析教程学习笔记(1)C到C++的升级
1.现代软件产品架构图 比如商场收银系统 2.C 到 C++ 的升级 2.1变量的定义 C++中所有的变量都可以在需要使用时再定义,而 C 语言中的变量都必须在作用域开始位置定义. 2.2 regis ...
- 《Spring源码深度解析》学习笔记——Spring的整体架构与容器的基本实现
pring框架是一个分层架构,它包含一系列的功能要素,并被分为大约20个模块,如下图所示 这些模块被总结为以下几个部分: Core Container Core Container(核心容器)包含有C ...
- 《C语言深度剖析》学习笔记----C语言中的符号
本节主要讲C语言中的各种符号,包括注释符.单引号双信号以及逻辑运算符等. 一.注释符 注释符号和注释在程序的预编译期就已经被解决了,在预编译期间,编译器会将注释符号和注释符号之间的部分简单的替换成为空 ...
- vue 3 学习笔记 (七)——vue3 中 computed 新用法
vue3 中 的 computed 的使用,由于 vue3 兼容 vue2 的选项式API,所以可以直接使用 vue2的写法,这篇文章主要介绍 vue3 中 computed 的新用法,对比 vue2 ...
- Webpack新手入门教程(学习笔记)
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; text-align: center; font: 30.0px Helvetica; color: #000000 } ...
随机推荐
- 初识Linux(三)--文件系统基本结构
Linux文件系统是一个倒立的单根树状结构,文件名称严格区分大小写(windows系统则是对大小写不明感的).路径用“/”分隔,跟windows的“\”不同. 这里我画了一张一般Linux系统的正常目 ...
- postgresql recovery.conf改变需要重启吗
之前在研究pgpoll时,发现trigger_file参数指定的文件存在后,会自动将standby节点提升为可写节点.不需要手动执行pg_ctl promote,但是这个时间一般有延迟,因为进程会定期 ...
- Git的origin和master分析
首先要明确一点,对git的操作是围绕3个大的步骤来展开的(其实几乎所有的SCM都是这样) 1. 从git取数据(git clone) 2. 改动代码 3. 将改动传回git(git push) 这3个 ...
- Tinker爬坑之路
目的 热修复去年年底出的时候,变成了今年最火的技术之一.依旧记得去年面试的时候统一的MVP,然而今年却变成了RN,热修复.这不得不导致我们需要随时掌握最新的技术.不然可能随时会被淘汰.记得刚进公司,技 ...
- apply 无循环拼接数组
apply()第二个参数只能是数组,这个数组将作为参数传给原函数的参数列表arguments. 其实在实际开发中,JS 继承的方法并不止这一种,使用原型链继承是更加常用的方式,此外还有构造函数继承,这 ...
- Metasploit的基本使用
Metasploit可以在Linux.Windows和Mac OS X系统上运行.我假设你已安装了Metasploit,或者你使用的系统是Kali Linux.它有命令行接口也有GUI接口. 我使用的 ...
- 类里边的构造函数可以被private修饰,在类的内部创建对象。利用这种特性创建单类模式
- 【JD的一人戏】之"小羊踢足球"第一篇
好多次加班后坐的士回家,副驾驶座位后内嵌的显示屏正好在播放一个美食节目,内容就是一个着装怪异的厨子把各种食材分门别类地摆在你面前,然后用小小的锅碗瓢盆慢慢的做出很精致的够一个人吃的分量的各种美食,做好 ...
- c语言编译执行过程
<h4>认识C编译执行过程</h4>认识C编译执行过程,是C学习的开端.简单说C语言从编码编译到执行要经历一下过程: C源代码编译---->形成目标代码,目标代码是在目标 ...
- 有状态与无状态 cookie session
服务器所维护的与客户交互活动的信息称为状态信息.不保存任何状态信息的服务器称为无状态服务器(stateless server),反之则称为有状态服务器(stateful server). 面向连接对应 ...