0.目录

1.动态内存分配

2.命名空间

3.强制类型转换

4.小结

1.动态内存分配

1.1 C++中的动态内存分配

  • C++中通过new关键字进行动态内存申请
  • C++中的动态内存申请是基于类型进行的
  • delete关键字用于内存释放

1.2 new关键字与malloc函数的区别

  • new关键字是C++的一部分
  • malloc是由C库提供的函数
  • new以具体类型为单位进行内存分配
  • malloc以字节为单位进行内存分配
  • new在申请单个类型变量时可进行初始化
  • malloc不具备内存初始化的特性

1.3 new关键字的初始化

2.命名空间

2.1 作用域与命名空间

在C语言中只有一个全局作用域:

  • C语言中所有的全局标识符共享同一个作用域
  • 标识符之间可能发生冲突

C++中提出了命名空间的概念:

  • 命名空间将全局作用域分成不同的部分
  • 不同命名空间中的标识符可以同名而不会发生冲突
  • 命名空间可以相互嵌套
  • 全局作用域也叫默认命名空间

2.2 命名空间的定义和使用

C++命名空间的定义:

C++命名空间的使用:

使用整个命名空间:using namespace name;

使用命名空间中的变量:using name::variable;

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

示例:

#include <stdio.h>

namespace First
{
int i = 0;
} namespace Second
{
int i = 1; namespace Internal
{
struct P
{
int x;
int y;
};
}
} int main()
{
using namespace First;
using Second::Internal::P; printf("First::i = %d\n", i);
printf("Second::i = %d\n", Second::i); P p = {2, 3}; printf("p.x = %d\n", p.x);
printf("p.y = %d\n", p.y); return 0;
}

运行结果:

[root@bogon Desktop]# g++ test.cpp
[root@bogon Desktop]# ./a.out
First::i = 0
Second::i = 1
p.x = 2
p.y = 3

3.强制类型转换

3.1 C方式的强制类型转换

C方式的强制类型转换:

示例:

#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(5); printf("p->x = %d\n", p->x);
printf("p->y = %d\n", p->y); return 0;
}

运行结果:

[root@bogon Desktop]# g++ test.cpp
[root@bogon Desktop]# ./a.out
Segmentation fault (core dumped)

编译器虽然可以编译通过,但是无法运行!

存在的问题:

  • 过于粗暴——任意类型之间都可以进行转换,编译器很难判断其正确性
  • 难于定位——在源码中无法快速定位所有使用强制类型转换的语句

问题:强制类型转换在实际工程中是很难完全避免的!如何进行更加安全可靠的转换?

3.2 C++的新式类型转换

C++将强制类型转换分为4个不同的类型:

static_cast强制类型转换——静态类型转换

  • 用于基本类型间的转换
  • 不能用于基本类型指针间的转换
  • 用于有继承关系类对象之间的转换和类指针之间的转换

const_cast强制类型转换

  • 用于去除变量的只读属性
  • 强制转换的目标类型必须是指针或引用

reinterpret_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); // Error
} void const_cast_demo()
{
const int& j = 1;
int& k = const_cast<int&>(j); const int x = 2;
int& y = const_cast<int&>(x); int z = const_cast<int>(x); // Error k = 5; printf("k = %d\n", k);
printf("j = %d\n", j); y = 8; printf("x = %d\n", x);
printf("y = %d\n", y);
printf("&x = %p\n", &x);
printf("&y = %p\n", &y);
} void reinterpret_cast_demo()
{
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
} void dynamic_cast_demo()
{
int i = 0;
int* pi = &i;
char* pc = dynamic_cast<char*>(pi); // Error
} int main()
{
static_cast_demo();
const_cast_demo();
reinterpret_cast_demo();
dynamic_cast_demo(); return 0;
}

运行结果为:

[root@bogon Desktop]# g++ test.cpp
test.cpp: In function ‘void static_cast_demo()’:
test.cpp:11: error: invalid static_cast from type ‘int*’ to type ‘char*’
test.cpp: In function ‘void const_cast_demo()’:
test.cpp:22: error: invalid use of const_cast with type ‘int’, which is not a pointer, reference, nor a pointer-to-data-member type
test.cpp: In function ‘void reinterpret_cast_demo()’:
test.cpp:47: error: invalid cast from type ‘int’ to type ‘char’
test.cpp: In function ‘void dynamic_cast_demo()’:
test.cpp:54: error: cannot dynamic_cast ‘pi’ (of type ‘int*’) to type ‘char*’ (target is not pointer or reference to class)

将出错的几行代码注释后:

#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); // Error
} void const_cast_demo()
{
const int& j = 1;
int& k = const_cast<int&>(j); const int x = 2;
int& y = const_cast<int&>(x); //int z = const_cast<int>(x); // Error k = 5; printf("k = %d\n", k);
printf("j = %d\n", j); y = 8; printf("x = %d\n", x);
printf("y = %d\n", y);
printf("&x = %p\n", &x);
printf("&y = %p\n", &y);
} void reinterpret_cast_demo()
{
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
} void dynamic_cast_demo()
{
int i = 0;
int* pi = &i;
//char* pc = dynamic_cast<char*>(pi); // Error
} int main()
{
static_cast_demo();
const_cast_demo();
reinterpret_cast_demo();
dynamic_cast_demo(); return 0;
}

运行结果为:

[root@bogon Desktop]# g++ test.cpp
[root@bogon Desktop]# ./a.out
k = 5
j = 5
x = 2
y = 8
&x = 0x7ffd5a6a5650
&y = 0x7ffd5a6a5650

4.小结

  • C++中内置了动态内存分配的专用关键字
  • C++中的动态内存分配可以同时进行初始化
  • C++中的动态内存分配是基于类型进行的
  • C++中命名空间概念用于解决名称冲突问题
  • C方式的强制类型转换
    1. 过于粗暴
    2. 潜在的问题不易被发现
    3. 不易在代码中定位
  • 新式类型转换以C++关键字的方式出现
    1. 编译器能够帮助检查潜在的问题
    2. 非常方便的在代码中定位
    3. 支持动态类型识别( dynamic_cast )

C++解析(8):C++中的新成员的更多相关文章

  1. C++深度解析教程学习笔记(4)C++中的新成员

    1. 动态内存分配 (1)C++通过 new 关键字进行动态内存申请,是以类型为单位来申请空间大小的 (2)delete 关键字用于内存释放 ▲注意释放数组时要加[],否则只释放这个数组中的第 1 个 ...

  2. 第10课 C++中的新成员

    1. 动态内存分配 (1)C++通过new关键字进行动态内存申请,是以类型为单位来申请空间大小的 (2)delete关键字用于内存释放 ▲注意释放数组时要加[],否则只释放这个数组中的第1个元素. [ ...

  3. 解析C#类中的构造函数

    <解析C#类中的构造函数> 一.  C#中的构造函数概述: C#中类包含数据成员和函数成员.函数成员提供了操作类中数据的某些功能,包括方法.属性.构造器和终结器.运算符和索引器. 构造函数 ...

  4. NET Framework 4 中的新 C# 功能

    http://msdn.microsoft.com/zh-cn/magazine/ff796223.aspx C# 编程语言自 2002 年初次发布以来已经有了极大的改善,可以帮助程序员编写更清晰易懂 ...

  5. [转]【译】.NET Core 3.0 中的新变化

    .NET Core 3.0 是 .NET Core 平台的下一主要版本.本文回顾了 .Net Core 发展历史,并展示了它是如何从基本支持 Web 和数据工作负载的版本 1,发展成为能够运行 Web ...

  6. 1 PHP 5.3中的新特性

    1 PHP 5.3中的新特性 1.1 支持命名空间 (Namespace) 毫无疑问,命名空间是PHP5.3所带来的最重要的新特性. 在PHP5.3中,则只需要指定不同的命名空间即可,命名空间的分隔符 ...

  7. 介绍一位OWin服务器新成员TinyFox

    TinyFox 是一款支持OWIN标准的WEB应用的高性能的HTTP服务器,是Jexus Web Server的"姊妹篇".TinyFox本身的功能是html服务器,所有的WEB应 ...

  8. Windows 10 版本 1507 中的新 AppLocker 功能

    要查看 Windows 10 版本信息,使用[运行]> dxdiag  回车 下表包含 Windows 10 的初始版本(版本 1507)中包括的一些新的和更新的功能以及对版本 1511 的 W ...

  9. TWaver家族新成员 — Legolas工业自动化设计平台

    对于TWaver可视化家族的成员,大家比较熟悉的是我们的网络拓扑图组件和MONO Design三维建模工具.作为开发工具,这两款产品面向广大的程序猿同志,在界面可视化上为大家省时省力.但是,当项目交付 ...

随机推荐

  1. springboot-vue-JWT使用

    springboot-vue-JWT使用 后端引入依赖: <dependency> <groupId>io.jsonwebtoken</groupId> <a ...

  2. linux命令提示符设置

    变成绿色 [root@localhost /usr/local]#vim /root/.bashrc # .bashrc # User specific aliases and functions a ...

  3. JUC——原子类操作(三)

    原子类操作 既然强调了并发访问,那么就必须考虑操作系统位数:32位操作系统还是64位操作系统,对于long型数据类型而言,是64位的.但是如果现在项目运行在32位系统上,则long型数据会占用32位空 ...

  4. Python-2.7 配置tab自动补全功能

    作者博文地址:http://www.cnblogs.com/spiritman/ 之前一直使用shell编程,习惯了shell的 tab 自动补全功能,而Python的命令行却不支持 tab 自动补全 ...

  5. spark RDD、DataFrame、DataSet之间的相互转化

    这三个数据集看似经常用,但是真正归纳总结的时候,很容易说不出来 三个之间的关系与区别参考我的另一篇blog  http://www.cnblogs.com/xjh713/p/7309507.html ...

  6. centos上搭建git服务--3

    前言:当我们想要实现几个小伙伴合作开发同一个项目,或者建立一个资源分享平台的时候,GIT就是一个很好的选择.当然,既然是一个共有平台,那么把这个平台放到个人计算机上明显是不合适的,因此就要在服务器上搭 ...

  7. CF刷刷水题找自信 2

    CF 1114A  Got Any Grapes(葡萄)? 题目意思:给三个人分葡萄,三个人对葡萄的颜色有一些要求,问所准备的三种颜色的葡萄能否满足三人的要求. 解题意思:直接按条件判断即可. #in ...

  8. Eclipse添加Jquery和javascript的智能提示

    使用Eclipse写Jquery和Javascript代码的时候,是没有智能提示的.我们可以使用一个插件来解决这个问题. 安装完成后,Eclipse会自动重启.重启之后,我们在项目上右键,   根据自 ...

  9. JAVA之路(一)

    距离做下复习JAVA并学好JAVA的决定已经过去一周了,我买了慕课网的JAVA入门视频,在图书馆借了三本关于JAVA的书——两本是JAVA入门经典,一本是JAVA WEB开发宝典.我的计划是短时间内复 ...

  10. QLayout窗口布局

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QLayout窗口布局     本文地址:http://techieliang.com/201 ...