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++中的新成员的更多相关文章

  1. C++深度解析教程学习笔记(6)对象的构造和销毁

    1. 对象的初始化 (1)从程序设计的角度看,对象只是变量,因此: ①在栈上创建对象时,成员变量初始化为随机值 ②在堆上创建对象时,成员变量初始化为随机值 ③在静态存储区创建对象时,成员变量初始化为 ...

  2. C++深度解析教程学习笔记(5)面向对象

    1. 面向对象基本概念 (1)面向对象的意义在于 ①将日常生活中习惯的思维方式引入程序设计中 ②将需求中的概念直观的映射到解决方案中 ③以模块为中心构建可复用的软件系统 ④提高软件产品的可维护性和可扩 ...

  3. C++深度解析教程学习笔记(3)函数的扩展

    1.内联函数 1.1.常量与宏的回顾 (1)C++中的 const 常量可以替代宏常数定义,如: ; //等价于 #define A 3 (2)C++中是否有解决方案,可以用来替代宏代码片段呢? 1. ...

  4. C++深度解析教程学习笔记(2)C++中的引用

    1.C++中的引用 (1)变量名的回顾 ①变量是一段实际连续存储空间的别名,程序中通过变量来申请并命名存储空间 ②通过变量的名字可以使用存储空间.(变量的名字就是变量的值,&变量名是取地址操作 ...

  5. C++深度解析教程学习笔记(1)C到C++的升级

    1.现代软件产品架构图 比如商场收银系统 2.C 到 C++ 的升级 2.1变量的定义 C++中所有的变量都可以在需要使用时再定义,而 C 语言中的变量都必须在作用域开始位置定义. 2.2 regis ...

  6. 《Spring源码深度解析》学习笔记——Spring的整体架构与容器的基本实现

    pring框架是一个分层架构,它包含一系列的功能要素,并被分为大约20个模块,如下图所示 这些模块被总结为以下几个部分: Core Container Core Container(核心容器)包含有C ...

  7. 《C语言深度剖析》学习笔记----C语言中的符号

    本节主要讲C语言中的各种符号,包括注释符.单引号双信号以及逻辑运算符等. 一.注释符 注释符号和注释在程序的预编译期就已经被解决了,在预编译期间,编译器会将注释符号和注释符号之间的部分简单的替换成为空 ...

  8. vue 3 学习笔记 (七)——vue3 中 computed 新用法

    vue3 中 的 computed 的使用,由于 vue3 兼容 vue2 的选项式API,所以可以直接使用 vue2的写法,这篇文章主要介绍 vue3 中 computed 的新用法,对比 vue2 ...

  9. Webpack新手入门教程(学习笔记)

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; text-align: center; font: 30.0px Helvetica; color: #000000 } ...

随机推荐

  1. 【pat-1074】宇宙无敌加法器(高精度)

    链接:https://www.patest.cn/contests/pat-b-practise/1074 地球人习惯使用十进制数,并且默认一个数字的每一位都是十进制的.而在PAT星人开挂的世界里,每 ...

  2. requests beautifulsoup

    requests Python标准库中提供了:urllib.urllib2.httplib等模块以供Http请求,但是,它的 API 太渣了.它是为另一个时代.另一个互联网所创建的.它需要巨量的工作, ...

  3. Node大文件处理

    之前有个需求要将文件解析再处理,当时直接将整个文件内容读到内存中然后解析,也是没有考虑到大文件的问题,那么要如何解析大文件呢? 输入:文件的内容是多个json,按顺序排列 输出:解析后的json数据 ...

  4. 服务器(Ubuntu 12.04 LTS)上编译基于OpenCV的项目遇到的问题及解决方案

    问题1:OpenCV编译安装时出错,错误信息中提到要打开-fPIC 选项重试. 解决方案:使用如下命令运行CMake cmake -DWITH_1394=OFF -DWITH_CUDA=OFF -DW ...

  5. 在C++中指针和引用传值区别

    笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解 ...

  6. 剑指Offer面试题:13.合并两个排序的链表

    一 题目:合并两个排序的链表 题目:输入两个递增排序的链表,合并这两个链表并使新链表中的结点仍然是按照递增排序的.例如输入下图中的链表1和链表2,则合并之后的升序链表如链表3所示. 二 代码实现 te ...

  7. IntelliJ IDEA中使用Git

    IntelliJ IDEA下使用Git IntelliJ IDEA下配置Git:git clone.git checkout.git diff.git log.git commit.git push. ...

  8. #503. 「LibreOJ β Round」ZQC 的课堂 容斥原理+Treap

    题目: 题解: 比较容易发现 : \(x,y\) 的贡献是独立的. 所以可以分开考虑. 假设我们考虑 \(x\).向量在 \(x\) 方向的投影依次是 : \(\{a_1,a_2, ... ,a_n\ ...

  9. PHP 操作XML文档

    <<<操作符需PHP5.3以上版本才能支持,下面程序在wamp环境下测试完成. <?php // Set the content type to be XML, so that ...

  10. PHP echo汉字出现乱码的情况之一

    当然首先要理清楚到底是web服务端造成,php造成的,还是数据库造成的. 需要在头文件里UTF-8 <head> <meta http-equiv="Content-Typ ...