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. Linux 下 的 Oracle,如何安装 tnsname

    运行 netca 即可:

  2. bzoj1854 [Scoi2010]游戏 ([SCOI2010]连续攻击游戏)

    bzoj1854 [Scoi2010]游戏 ([SCOI2010]连续攻击游戏) 据说正解是并查集???我不会 这不是一道匈♂牙利好题吗??? 一个装备的两个属性都向它连边,然后跑一遍匈♂牙利 注意: ...

  3. 在CentOS 7下编译安装Nginx+PHP+MySQL环境

    本文转载自:http://www.softeng.cn/?p=156,本文已获得作者授权,未经作者同意,不可转载. 1.前言 本文适合于已经对Linux操作系统具有基本操作经验,并且能够在Linux或 ...

  4. javaweb(三十四)——使用JDBC处理MySQL大数据

    一.基本概念 大数据也称之为LOB(Large Objects),LOB又分为:clob和blob,clob用于存储大文本,blob用于存储二进制数据,例如图像.声音.二进制文等. 在实际开发中,有时 ...

  5. CentOS7.2 部署Haproxy 1.7.2

    原文发表于cu:2017-03-16 参考文档: haproxy:http://www.haproxy.org/ 本文涉及haproxy的安装,并做简单配置. 一.环境准备 1. 操作系统 CentO ...

  6. 如何更改Arcmap里经纬度小数点后面的位数?

    customize>arcmap option>data view >round coordinate to 改成想要显示的小数位数

  7. MySQL 中的数据类型介绍

    1.MySQL 数据类型 MySQL中定义数据字段的类型对你数据库的优化是非常重要的. MySQL支持多种类型,大致可以分为三类:数值.日期/时间和字符串(字符)类型. 2.数值类型(12) 2.1. ...

  8. 王者荣耀交流协会-Alpha发布用户使用报告

    用户数量:10人 姓名如下(包括化名):张小斌.王瑞瑞.蛋蛋.小美.晨曦.小丽.张利刚.小闫.小谢.小崔 寻找的用户多为王者荣耀交流协会成员的同学,对管理时间有着强烈的需求,也对PSP Daily软件 ...

  9. 福大软工1816:Beta(3/7)

    Beta 冲刺 (3/7) 队名:第三视角 组长博客链接 本次作业链接 团队部分 团队燃尽图 工作情况汇报 张扬(组长) 过去两天完成了哪些任务 文字/口头描述 参与开发关键词提醒部分 展示GitHu ...

  10. ubuntu关闭系统自动检测错误

    sudo gedit /etc/default/apport 将enabled=1 改成 enabled=0