新的关键字(记录+理解)

动态内存分配

  • C++中的动态内存分配
    —C++中通过new关键字进行动态内存申请(malloc属于标准C,不属于C++)
    —C++中的动态内存申请时基于类型进行的
    —delete关键字用于内存释放

变量申请:
Type* pointer = new Type;
// ……
delete pointer;

数组申请:
Type* pointer = new Type[N];
// ……
delete[] pointer;

int main()
{
    int * p = new int;

    *p = 5;
    *p = *p + 10;

    printf("p = %p\n",p);
    printf("*p = %d\n,*p");

   delete p;   // 将p指向的堆空间中的1int大小内存释放

    p = new int[10];

    for(int i=0;i<10;i++)
    {
    p[i] = i + 1;

    printf("p[%d] = %d\n",i,p[i]);
    }

    delete[] p;   // 将p指向的堆空间中的整个数组大小(10int大小内存)释放
                  //如果只是delete p;则会造成内存泄漏(9int大小内存泄漏)

    printf("Press any key to continue...");
    getchar();
    teturn 0;
}

  • new关键字与malloc函数的却别
    *new关键字时C++的一部分,malloc时由C库提供的函数(在C++中照样能调用malloc,因为malloc只是一个函数)
    *new以具体类型为单位进行内存分配,malloc只能以字节为单位进行内存分配
    *new在申请单个类型变量时可进行初始化,malloc不具备内存初始化的特性

  • new关键字的初始化

int main()
{
    int* pi = new int[1];
    int* pf = new float[2.0f];//这里2.0f中的f表示2.0是一个浮点数
    char* pc = new char['c'];

    printf("*pi = %d\n",*pi);
    printf("*pf = %d\n",*pf);
    printf("*pc = %d\n",*pc);

    delete pi;
    delete pf;
    delete pc;

    printf("Press ang key to continue ...");
    getchar();
    return 0;
}

C++中的命名空间

  • 在C语言中只有一个全局作用域
    *C语言中所有的全局标识符共享同一个作用域
    (标识符之间可能发生冲突)
  • C++中提出了命名空间的概念
    *命名空间将全局作用域分成不同的部分
    *不同命名空间中的标识符可以同名而不会发生冲突
    *命名空间可以互相嵌套
    *全局作用域也叫默认命名空间

  • C++命名空间的定义:namespace name{…}

//以下编译能通过,因为,虽然定义了2个int i 但是命名空间将全局作用域分成不同的部分
namespace First
{
    int i = 0;
}

namespace Second
{
    int i = 1;

    namespace Internal
    {
        struct P
        {
            int x;
            int y;
        };
    }
}

int main()
{
    printf("Press any key to continue ...");
    getchar();
    return 0;
}

  • C++命名空间的使用:
    *使用整个命名空间:using namespace name;
    *使用命名空间中的变量:using name::variable;
    *使用默认命名空间中的变量: ::variable

默认情况下可以直接使用默认命名空间中的所有标识符

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("i = %d\n",i);
    printf("i = %d\n",Second::i);

    P p = {2,3};

    printf("p.x = %d\n",p.x);
    printf("p.y = %d\n",p.y);

    printf("Press any key to continue ...");
    getchar();

    return 0;
}

强制类型转换

  • C方式的强制类型转换
    (Type)(Expression) or Type(Expression)
//以下程序虽然编译通过,但是运行是不成功的。
//C方式的强制类型转换很容易通过,但不一定运行得到你想要的结果(因为编译通过并不代表合理)
typedef void(PF)(int);//定义一个函数类型,参数是1个int类型的值,返回值无的函数类型,这个函数类型名为PF

struct Point
{
    int x;
    int y;
};

int main()
{
    int v = 0x12345;
    PF* pf = (PF*)v;
    char c = char(v);

    pf(v);

    point* po = (Point*)v;

    printf("(%d,%d)\n",po->x,po->y);

    return 0;
}
  • C方式强制类型转换存在的问题
    ->过于粗暴
    __->任意类型之间都可以进行转换,编译器很难判断其正确性
    ->难于定位
    __->在源码中无法快速定位所有使用强制类型转换的语句

在程序设计理论中强制类型转换是不被推荐的,与goto语句一样,应该尽量避免。


  • 强制类型转换在实际工程中还是可能使用的
    如何进行更加安全可靠的转换?
  • C++将强制类型转换分为4种不同的种类

    • 强制类型转换
static_castconst_cast
dynamic_castreinterpret

用法:XXX_cast< Type >(Expression)

  • static_cast强制类型转换
    __用于基本类型间的转换,但不能用于基本类型指针间的转换
    __用于有继承关系类对象之间的转换和类指针之间的转换
int main()
{
    int i = 0;
    char c = 'c';
    int* pi = &i;
    char* pc = &c;

    c = static_cast<char>(i);//OK!
    pc = static_cast<char*>(pi);//Oops!//不能用于基本类型指针间的转换

    return 0;
}

static_cast是编译期进行转换的,无法在运行时检测类型,所以类类型之间的转换可能存在风险


  • **const_cast强制类型转换
    __用于去除变量的const属性
int main()
{
    const int& j = 1;//const引用,功能是定义的变量不能作为左值使用,但是依然可以用指针解引用的方式去改变其存放的值。这里用了另外的方式去改变其值
    int& k = const_cast<int&>(j);//先去除变量j的const的属性,然后为变量j另外取一个名字k(注意:这只是在这一句实现了k的一种功能,不能改变j的功能,j的功能在上一句已经定好了!)
    const int x = 2;
    int& y = const_cast<int&>(x);//先去除变量x的const属性让其变成普通变量,然后为这个普通变量x取一个别名y(注意:这只是在这一句实现了y的一种功能,不能改变x的功能,x的功能在上一句已经定好了!)同时也为x(y是其别名)了一块存储空间,但是这个存储空间很神奇,因为每次使用到x的时候都是从常量表中去取2这个值,所以这个空间基本就是给y用的,但是x和y又是一个东西,哈哈哈。

    k = 5;
    printf("j = %d\n",j);//打印出5,因为k是j的别名,k的值改变了,j也就改变了
    printf("k = %d\n",k);//打印出5,这个很明显,k = 5

    y = 3;

    printf("x = %d\n",x);//由于const int定义的,所以x是存放在常量表里面的一个常量值2
    printf("y = %d\n",x);//很明显y = 3
    printf("&x = %p\n",&x);//这里x和y的地址是一样的。虽然x和y的值不同,那是因为x和y所代表的存储空间虽然是同一个,但是每次使用x变量不是从存储空间去取值而是从常量表里去取值,所以x的值都是2;但是y却不是一个常量,所以一旦改变了存储空间中的值,y的值就改变了;
    printf("&y = %p\n",&y);表的那个存储空间是相同的

    return 0;
}

  • reinterpret_cast强制类型转换
    __用于指针类型间的强制转换
    __用于整数和指针类型间的强制转换
typedef void(PF)(int);

int main()
{
    int i = 0;
    char c = 'c';
    int* pi = reinterpret_cast<int*>(&c);
    char* pc = reinterpret_cast<char*>(&i);
    PF* pf = reinterpret_cast<PF*>(0x12345678);

    c = reinterpret_cast<char>(i);//Oops! static_cast实现基本类型间的转换
}

reinterpret_cast直接从二进制位进行赋值,是一种极其不安全的转换。


  • dynamic_cast强制类型转换
    *主要用于类层次间的转换,还可以用于类之间的交叉转换
    *dynamic__cast具有类型检查的功能,比static_cast更安全

类是什么?对象是什么?类层次又是什么?


小结

  • C++中内置了动态内存分配的专用关键字
  • C++中的动态内存分配是基于类型进行的
  • C++中命名空间概念用于解决名称冲突问题
  • C++细化了C语言中强制类型转换的方式
    ——C++不推荐在程序中使用强制类型转换
    ——C++建议在强制类型转换时考虑一下究竟希望什么样的转换

下面将开始学习面向对象程序的设计了!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
按下述要求编写一个可以在code::block上运行的以班为单位进行通讯录信息管理。每个记录包括:序号、姓名、性别、年龄电话、籍贯、家庭住址、通信地址及邮编程序软件 用户登录:设计一个用户数据库,存储用户名和密码。用户输入用户名和密码后,系统在数据库中进行验证。如果三次输入错误,则自动退出系统。 主菜单:设计一个主菜单,包括输入/添加/插入、显示/查询、修改、统计和排序等功能。用户可以根据需要选择相应的功能。 输入/添加/插入记录:设计一个记录数据库,存储每个记录的信息,包括序号、姓名、性别、年龄、电话、籍贯、家庭住址、通信地址及邮编等。用户可以输入记录,或者在已有记录中添加或插入数据。 显示/查询记录:用户可以按照关键字查询记录,例如姓名、电话等。系统会显示与关键字匹配的所有记录的各项信息。 修改记录:用户可以选择要修改的记录,进行修改操作。系统会显示记录信息,用户进行修改后,需要保存到数据库中。 统计功能:用户可以选择要统计的关键字,例如年龄、籍贯等。系统会对所有记录进行统计,计算总分、平均分、分段信息等。 排序:用户可以选择按照某一关键字或某几个关键字的组合对记录进行排序。系统会对记录进行排序,并显示排序后的结果。
06-09

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值