【啃书系列】【C++ Primer Plus】【一】基础知识

一、基础知识

1. 名称空间

  • 产生原因:

    厂商将代码封装成产品,但是两个厂商的函数有重名的情况发生,会产生误解

  • 解决办法:

    A公司将其产品放到名为A的名称空间中;B公司则放到B的名称空间中。这样就可以采用如下方法进行区分

    A::Run();
    B::Run();
    
  • std:

    类、函数、变量等都是C++编译器的标准组件,都被放在std名称空间中。所以其实可以省略using而用std::cin >> a;等进行代码编写,然而这样面对大项目还是会出现问题,因此我们用

    using std::cin;
    using std::cout;
    using std::endl;
    

    等来包含一些可用函数(不用打命名空间名称std)

2. cin和cout

  • 概念:

    1. 输出是一个流,<<运算符的作用是将右边的东西插入到流中

    2. 输入也是一个流,>>运算符从输入流中抽取字符

    3. <<和>>符号用来表示信息流的方向

    4. endl确保程序继续运行前刷新输出,而‘\n’没有这样的保证,意味着有时输入信息后才会出现提示

  • 以两个下划线或下划线和大写字母开头的名称被保留给实现(编译器及其使用的资源)使用。以一个下划线开头的名称被保留给实现,用作全局标识符

  • 大括号初始化int a{};或者int b = {};,如果没有数据,则会初始化为0

  • 更改输出进制

    cout << oct;
    cout << hex;
    cout << dec;
    cout.setf(ios_base::boolalpha);		// 输出的值将转化为布尔值
    
  • 读取整行带空格不带回车的字符时使用cin.getline(name, size);(string数组改其中值内存地址咋变的?——string实质上是一个指针,指向首字母,所以string的size都是32位,而且数组里string地址连续)

  • raw字符串:string R"(asdaffergrgr)";只显示括号内的内容,完全照搬,引号括号之间可以自己加东西定义边界

3. 结构体

  • 制定占用特定位数的结构成员,创建与某个硬件设备上的寄存器对应的数据结构方便,可以使用没有名称的字段来提供间距

    struct torgle_register{
        unsigned int SN : 4;	// 4 bits for SN value
        unsigned int : 4;		// 4 bits unused
        bool goodIn : 1;		// valid input (1 bit)
        bool goodTorgle : 1;	// successful torgling
    };
    
  • 共用体:能储存不同数据类型,但只能同时储存一种(可以放在结构体里面),常用于节省内存

    union one4all{		// 去掉one4all是匿名共用体,成员为位于相同地址处的变量,因此需要标识符,表明
        int i;			// 哪个变量正在活动
        long l;
        double d;
    };
    
  • 枚举(enum):创建符号常量,可以代替constenum colors{red, orange, blue};(colors可省略)作用是创建类似结构体的colors,把大括号中名称均作为常量,赋值0~2,常用于定义符号常量(switch)

    enum colors{red, orange, blue};		// 仅有赋值运算符,但可以单向转换为int
    colors c;
    c = red;		// valid
    c = 2000;		// invalid
    
    enum {g = 1, kg = 1000, t = 1000000, unknown};	// unknown = 1000001
    
  • 计算结构体大小的规则(字节对齐):

    1. 每一个成员的偏移量都必须是该成员的倍数。

    2. 结构体的大小必须是该结构体字节数最大成员的倍数。

4. 指针和自由存储空间

  • 为什么用指针?因为指针快啊!一个地址才多大!

  • 在创建指针时,计算机将分配用来存储地址的内存,但不会分配用来存储指针所指向的数据的内存!

    int* fellow;		// 未分配地址,可能有任何值
    *fellow = 233;		// 野指针出现了!
    
  • 面试常见题

new/delete和malloc/free的区别
  1. 参数

使用new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算。而malloc则需要显式地指出所需内存的尺寸。

  1.   返回类型
    

new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换,故new是符合类型安全性的操作符。而malloc内存分配成功则是返回void* ,需要通过强制类型转换将void*指针转换成我们需要的类型。

  1.   分配失败
    

new内存分配失败时,会抛出bac_alloc异常。malloc分配内存失败时返回NULL。

  1.  自定义类型
    

new会先调用operator new函数,申请足够的内存(通常底层使用malloc实现)。然后调用类型的构造函数,初始化成员变量,最后返回自定义类型指针。delete先调用析构函数,然后调用operator delete函数释放内存(通常底层使用free实现)。

malloc/free是库函数,只能动态的申请和释放内存,无法强制要求其做自定义类型对象构造和析构工作。

  1. 重载

C++允许重载new/delete操作符,特别的,布局new的就不需要为对象分配内存,而是指定了一个地址作为内存起始区域,new在这段内存上为对象调用构造函数完成初始化工作,并返回此地址。而malloc不允许重载。

  1.   内存区域
    

new操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。而堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序的内存动态分配,C语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。自由存储区不等于堆,如上所述,布局new就可以不位于堆中。

  • delete会删除指针指向的内容,但是不会删除指针。一定要配对使用new和delete,否则会发生内存泄漏,也就是分配的内存再也无法使用了

  • 一个已经释放的内存块不能再被delete;delete只能释放new出来的东西;delete空指针是安全的。
    常见错误(瞿老师常说的):两个指向同一内存块的指针被delete,如string等号赋值后delete两个,解决办法:先申请内存,再用strcpy/strncpy

    // strncpy用法
    char food[20];
    strncpy(food, "asdasdasdasdasdasdasdasdasdasdasd", 19);
    food[19] = '\0';
    
  • sizeof(pArray);指针的大小,sizeof(array);数组的长度

  • 如何打印char类型指针的地址而不是打印出字符串来?将其强制转化为其它类型的指针cout << (int *) pChar;

  • 自动存储、静态存储和动态存储

    1. 自动存储

      在函数内部定义的常规变量使用自动存储空间,被称为自动变量,在函数调用时产生,结束时消亡。自动变量是一个局部变量,通常存储在中,后进先出。程序执行时,栈会不断增大缩小,内存是连续的

    2. 静态存储

      整个程序执行期间都存在的存储方式,定义方法是全局变量或static

    3. 动态存储
      new和delete管理了一个内存池,被称为自由存储空间,该内存池与静态变量和自动变量的内存是分开的,所以我们可以在一个函数中new,另一个函数中delete。也是因此,占用的自由存储区可能不连续

栈、堆和内存泄漏

如果在自由存储空间(或堆)上new出来的变量没有delete,会怎么样?

即使包含指针的内存由于一些原因被释放,自由存储空间内分配的变量也将继续存在

我们将无法访问这些结构,因为指向这些内存的指针无效

这将导致内存泄漏

被泄露的内存在程序的整个生命周期内都不可用,也无法被收回(退出程序后系统基本会清理)。如果内存耗尽或是占用了其它在这些内存空间中运行的应用程序,则会崩溃

5. 数组的替代品

  • 数组

    a1[-2] = 20;是允许的,按内存空间分配,数组的效率最高

  • vector

    虽然同样允许,但是可以用a2.at(3)语句来禁止,代价是效率变低

    另外,vector对象本身在栈中,而vector中的数据存放在堆中

  • array

    长度固定、使用栈(静态内存分配)、效率与数组相同但是更安全

    #include<array>
    ...
    array<int, 5> ai;	// 不能用变量长度创建
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值