void*指针

void关键字表示“空类型”的概念。但是,这里的“空类型”不表示“任意类型”,而是表示不存在的意思,也就是说C/C++不允许你写语句void a,不存在类型为void的东西.

void*表示“空类型指针”,与void不同,void*表示“任意类型的指针”或表示“该指针与一地址值相关,但是不清楚在此地址上的对象的类型”。

类型转换

C风格转换:

 int i;
double d; i = (int) d;
//或
i = int (d);

C风格转换在C++中是适用的。但是C++也提供了4种转换方法。

那为什么还需要一个新的C++类型的强制转换呢?

新类型的强制转换可以提供更好的控制强制转换过程,允许控制各种不同种类的强制转换。C++中风格是static_cast<type>(content)。C++风格的强制转换其他的好处是,它们能更清晰的表明它们要干什么。程序员只要扫一眼这样的代码,就能立即知道一个强制转换的目的。

C++转换:

static_cast(exp)

用于相关类型之间的转换,诸如:在同一个类的继承层次关系中,向上或向下转换;枚举类型与整数类型之间的转换;浮点类型与指数类型之间的转换。

static_cast它能在内置的数据类型间互相转换,对于类只能在有联系的指针类型间进行转换。可以在继承体系中把指针转换来、转换去,但是不能转换成继承体系外的一种类型

 class A { ... };
class B { ... };
class D : public B { ... };
void f(B* pb, D* pd)
{
D* pd2 = static_cast<D*>(pb); // 不安全, pb可能只是B的指针
B* pb2 = static_cast<B*>(pd); // 安全的
A* pa2 = static_cast<A*>(pb); //错误A与B没有继承关系
...
}

reinterpret_cast(exp)

字面理解即re-interpret,重新解析(释)的意思。故名思意,它主要用于不相关类型之间的转换,好一个英文单词在不同的上下文中,词性和词义可能完全不同。它为不同类型之间转换带来的便利,但是也伴随着风险的,如将一个十六进制整数转换为内存地址(由int-->指针类型,这两种类型完全不关联)。既然是用于不相关类型之间的转换,也就意味着编译器不会做太多的确认和承诺。
reinterpret_cast方式还有一个特点就是:目标和原始值之间至少有相同的位数,我们可以将转换之后的值再转换回去,而不像其它3种类型可能会导致精度丢失。

dynamic_cast(exp)

一种运行时(run-time)检测的类型转换,因此转换可能需要较大的运行时代价,这种类型也是用C-style是无法实现的。主要用于执行类型向下转换和继承之间的转换。

dynamic_cast 仅能应用于指针或者引用,不支持内置数据类型
表达式dynamic_cast<T*>(a) 将a值转换为类型为T的对象指针。如果类型T不是a的某个基类型,该操作将返回一个空指针。
它不仅仅像static_cast那样,检查转换前后的两个指针是否属于同一个继承树,它还要检查被指针引用的对象的实际类型,确定转换是否可行。

const_cast(exp)

用于消除变量的const限定,转换之后的变量就不再具有“const”了,如果是一个const指针的话,转换之后可以改变指向而指向其它对象。

说明:

通常情况下dynamic_cast最好些,它检查的更严格些,其次是static_cast,而后两者也就是const_cast和reinterpret_cast较之前两者貌似不太常用,而且也不推荐使用,const_cast在用于去除const的地方还是有所发挥的,reinterpret_cast在转换时,不会在内存中进行补足比特位(例如int转换到double,需要补足4字节),这往往是不安全的,而且代码也是不可移植的。

动态内存分配

一般来说,编译器将内存分为三部分:静态存储区域、栈、堆。静态存储区主要保存全局变量和静态变量,栈存储调用函数相关的变量、地址等,堆存储动态生成的变量。 在c中是指由malloc,free运算产生释放的存储空间,在c++中就是指new和delete运算符作用的存储区域。

对象创建的两种方式:

类示例:

 #include <iostream>
using namespace std; class TestNew
{
private:
int ID;
public:
TestNew(int ID);
~TestNew();
}; TestNew::TestNew(int ID)
{
this->ID = ID;
} TestNew::~TestNew()
{
std::cout<<"对象 "<<this->ID<<" 执行析构函数"<<std::endl;
}

方法一:

ClassName object(param);

 TestNew test();

这样就声明了一个ClassName类型的object对象,C++会为它分配足够的存放对象所有成员的存储空间。
这种方法创建的对象,内存分配是分配到栈中的,由C++缺省创建和撤销,自动调用构造函数和析构函数。
该方法创建的对象调用类方法时,必须用“.”,而不能用“->”。

在函数中使用该方法时,函数内局部变量的存储单元都在栈上创建,函数执行结束后在将这些局部变量的内存空间回收。
在栈上分配内存空间效率很高,但是分配的内存容量有限。

方法二:

ClassName *object=new ClassName(param);
delete object;

 TestNew *pTest = new TestNew();
delete pTest;

C++用new创建对象时返回的是一个对象指针,object指向一个ClassName的对象,C++分配给object的仅仅是存放指针值的空间。
用new 动态创建的对象必须用delete来撤销该对象。只有delete对象才会调用其析构函数。
new创建的对象不是用“*”或“.”来访问该对象的成员函数的,而是用运算符“->”;

new创建类对象特点:

  1. new创建类对象需要指针接收,一处初始化,多处使用
  2. new创建类对象使用完需delete销毁
  3. new创建对象直接使用堆空间,而局部不用new定义类对象则使用栈空间
  4. new对象指针用途广泛,比如作为函数返回值、函数参数等

C++学习笔记(十一):void*指针、类型转换和动态内存分配的更多相关文章

  1. JVM学习笔记-第三章-垃圾收集器与内存分配策略

    JVM学习笔记-第三章-垃圾收集器与内存分配策略 tips:对于3.4之前的章节可见博客:https://blog.csdn.net/sanhewuyang/article/details/95380 ...

  2. C++ primer plus读书笔记——第12章 类和动态内存分配

    第12章 类和动态内存分配 1. 静态数据成员在类声明中声明,在包含类方法的文件中初始化.初始化时使用作用域运算符来指出静态成员所属的类.但如果静态成员是整形或枚举型const,则可以在类声明中初始化 ...

  3. 深入理解Java虚拟机学习笔记(二)-----垃圾收集器与内存分配策略

    写在前面 本节常见面试题: 如何判断对象是否死亡(两种方法). 简单的介绍一下强引用.软引用.弱引用.虚引用(虚引用与软引用和弱引用的区别.使用软引用能带来的好处). 如何判断一个常量是废弃常量 如何 ...

  4. [学习笔记]Java代码中各种类型变量的内存分配机制

    程序运行时,我们最好对数据保存到什么地方做到心中有数.特别要注意的是内存的分配.有六个地方都可以保存数据: (1) 寄存器 这是最快的保存区域,因为它位于和其他所有保存方式不同的地方:处理器内部.然而 ...

  5. c++学习笔记(六)- vector使用和内存分配

    -----------------------------2019/01/15------------------------------- 复习了下迭代器,其实c++参考里讲的很清楚,主要需要辨析规 ...

  6. 网易云课堂_C语言程序设计进阶_第二周:指针:取地址运算和指针、使用指针、指针与数组、指针与函数、指针与const、指针运算、动态内存分配_2信号报告

    2 信号报告(5分) 题目内容: 无线电台的RS制信号报告是由三两个部分组成的: R(Readability) 信号可辨度即清晰度. S(Strength)    信号强度即大小. 其中R位于报告第一 ...

  7. python3.4学习笔记(十一) 列表、数组实例

    python3.4学习笔记(十一) 列表.数组实例 #python列表,数组类型要相同,python不需要指定数据类型,可以把各种类型打包进去#python列表可以包含整数,浮点数,字符串,对象#创建 ...

  8. Go语言学习笔记十一: 切片(slice)

    Go语言学习笔记十一: 切片(slice) 切片这个概念我是从python语言中学到的,当时感觉这个东西真的比较好用.不像java语言写起来就比较繁琐.不过我觉得未来java语法也会支持的. 定义切片 ...

  9. Go语言学习笔记九: 指针

    Go语言学习笔记九: 指针 指针的概念是当时学C语言时了解的.Go语言的指针感觉与C语言的没啥不同. 指针定义与使用 指针变量是保存内存地址的变量.其他变量保存的是数值,而指针变量保存的是内存地址.这 ...

随机推荐

  1. java:复写equals实例

    class User { String name; int age; /* *比较过程思路: *1.两个对象指向位置相同,那么他们就相等,return后跳出函数,不再往下执行 *2.指向位置不同,有3 ...

  2. Android:ScaleType设置图片

    设置例子:ImageViewId.setScaleType(ScaleType.CENTER); ScaleType:设置图片显示方式 效果预览:

  3. Apache James搭建内网邮件服务器

    Apache James搭建内网邮件服务器 极客521 | 极客521 2014-08-21 148 阅读 java 大概之前两个礼拜的日子,讨论会介绍了关于了.net内网邮件服务器的搭建.所以自己也 ...

  4. 1890. Money out of Thin Air(线段树 dfs转换区间)

    1890 将树的每个节点都转换为区间的形式 然后再利用线段树对结点更新 这题用了延迟标记 相对普通线段树 多了dfs的转换 把所要求的转换为某段区间 RE了N次 最后没办法了 记得有个加栈的语句 拿来 ...

  5. poj 2635 The Embarrassed Cryptographer(数论)

    题目:http://poj.org/problem?id=2635 高精度求模  同余模定理. 题意: 给定一个大数K,K是两个大素数的乘积的值.再给定一个int内的数L 问这两个大素数中最小的一个是 ...

  6. poj 3278 Catch That Cow (bfs)

    题目:http://poj.org/problem?id=3278 题意: 给定两个整数n和k 通过 n+1或n-1 或n*2 这3种操作,使得n==k 输出最少的操作次数 #include<s ...

  7. LeetCode Pascal's Triangle II (杨辉三角)

    题意:给出杨辉三角的层数k,返回最后一层.k=0时就是只有一个数字1. 思路:滚动数组计算前一半出来,返回时再复制另一半.简单但是每一句都挺长的. 0ms的版本: class Solution { p ...

  8. apache开源项目--HBase

    HBase – Hadoop Database,是一个高可靠性.高性能.面向列.可伸缩的分布式存储系统,利用HBase技术可在廉价PC Server上搭建起大规模结构化存储集群. HBase是Goog ...

  9. ORACLE参数文件

    一.oracle pfile/spfile区别    pfile 默认的名称为“init+例程名.ora”文件路径:E:\oracle\product\10.2.0\db_1\dbs,这是一个文本文件 ...

  10. (十二)学习CSS之box-sizing 属性

    参考:http://www.w3school.com.cn/cssref/pr_box-sizing.asp CSS3 box-sizing 属性 定义和用法 box-sizing 属性允许您以特定的 ...