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. centos7下将java -jar命令运行一个项目做成systemd服务

    有些时候运行一个java项目在linux下通过一条简单的java命令即可,如: #nohup java -jar jenkins.war & ###这里为后台运行jenkins 在此背景下,j ...

  2. OpenCV中Mat操作clone() 与copyto()的区别

    OpenCV中Mat操作clone() 与copyto()的区别 // Mat is basically a class with two data parts: the matrix header ...

  3. OpenStack入门篇(五)之KVM性能优化及IO缓存介绍

    1.KVM的性能优化,介绍CPU,内存,IO性能优化 KVM CPU-->qemu进行模拟ring 3-->用户应用 (用户态,用户空间)ring 0-->操作系统 (内核态,内核空 ...

  4. java 文件过滤

    public class TestFileio { public static void main(String[] args) { File file = new File("D:/upl ...

  5. 解决Extjs有IE下z-index属性的问题

    在用Extjs时,有时候,在Google浏览器上面没有任何问题,但是相同的页面在IE下面就会有问题,直接报错,点击中断,进行后可以看到如下的信息: Google里面没这个问题,加一句代码就能解决在窗体 ...

  6. EmitMapper自动映射工具

             在实体与DTO之间,我们一般都需要进行映射.如果手动的来进行转换,实在是太麻烦.所以就产生了很多映射工具,比如AutoMapper,EmitMapper.而经过一些对比,EmitMa ...

  7. runtime如何实现weak属性

    首先了解weak是一种非拥有关系,属性所值对象销毁时,属性值会清空(nil). Runtime对注册的类会进行布局,对于weak对象会放入hash表中,用weak指向的内存地址作为key,当对象引用计 ...

  8. VIN码/车架号的详解,车架号识别,VIN码识别,OCR车架号识别能带来什么

    各位车主在车检时不知道有没有注意到一件事,就是工作人员会打开车前盖在前围钢板上拓一张条码.下面来给大家介绍一下,这张条码就是VIN号,俗称钢印号,就像我们每个人都有自己的身份证号码一样,这也是汽车界的 ...

  9. [转载]文件系统缓存dirty_ratio与dirty_background_ra

    原文地址:文件系统缓存dirty_ratio与dirty_background_ratio两个参数区别作者:vincent 这两天在调优数据库性能的过程中需要降低操作系统文件Cache对数据库性能的影 ...

  10. Hands on Machine Learning with sklearn and TensorFlow —— 一个完整的机器学习项目(加州房地产)

    数据集地址:https://github.com/ageron/handson-ml/tree/master/datasets 先行知识准备:NumPy,Pandas,Matplotlib的模块使用 ...