C++碎碎念

头文件中ifndef/define/endif的作用

保证即使头文件被包含多次,也只定义一次,起到预编译保护作用。

extern “C”

程序中的变量或函数,经CC++编译器编译后后,符号不一样,会导致编译后的C代码在符号库中找不到。extern “C”告诉编译器这是C代码,按照C的方式编译。
所以,extern “C”的目的是解决符号匹配问题,实现CC++混合编程。

const#define

  • 都可以定义常量,const用途更广,比如修饰函数返回值和参数
  • const有数据类型,编译器可以对其进行类型安全检查,对#define只会进行字符替换

sizeofstrlen

  • sizeof是运算符,strlen是函数
  • sizeof可以用类型做参数,strlen只能用\0结尾的char *

指针和引用

  • 定义指针时可以不初始化;定义引用时必须初始化
  • 指针赋值是把指针指向另一个对象;引用赋值是修改引用绑定的对象的值
    在底层,引用变量由指针按照指针常量的方式实现,所以int i = 2;int* const gi = &i;int i = 2;int &gi = i;是一致的。

空指针、野指针和悬垂指针

  • 空指针:指向地址为空的指针(NULL指针)。可以被多次delete
  • 野指针:指向垃圾内存的指针。产生原因是创建时未初始化,它将会随意指向一个内存地址
  • 悬垂指针:动态创建的对象被释放或回收了,但是指向该对象的指针未做任何修改,仍旧指向已经回收的内存地址

malloc/freenew/delete

  • malloc/freeC/C++标准库函数,new/deleteC++运算符
  • 申请的是堆里面的内存空间
  • malloc不会做初始化,new有默认的初始化同时可以指定初始化。对于类类型而言,对象在创建的时候要自动执行构造函数,消亡之前要调用析构函数,malloc/free不能满足要求。malloc/free是库函数而不是运算符,不在编译器控制之内,不能把执行构造函数和析构函数的任务强加给它,因此,C++还需要malloc/free

#pragma once#ifndef/#define/#endif

  • #pragma once是编译相关,某些编译器可能不能用,移植性差一些;#ifndef/#define/#endif是语言相关
  • #ifndef/#define/#endif依赖于宏名字不能冲突,这不光可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件不会被不小心同时包含;缺点是如果不同头文件的宏名不小心“撞车”,可能会导致头文件明明存在,编译器却说找不到声明的状况
  • #pragma once由编译器提供保证同一个文件不会被包含多次。“同一个文件”是指物理上的一个文件,而不是指内容相同的两个文件,所以对应的缺点就是如果某个头文件有多份拷贝,将不能保证他们不被重复包含。当然,相比宏名碰撞引发的“找不到声明”的问题,重复包含更容易被发现并修正

NULLnullptr

C中,NULL通常定义为#define NULL ((void *)0)void *可以隐式转换成其他类型
C++是强类型的,void *不能隐式转换成其他指针类型,所以通常情况下编译器在头文件中会这样定义NULL

1
2
3
4
5
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif

所以C++中用0表示空指针。不过还是有缺陷不完美,处理重载函数的时候会出现问题。于是C++11引入了nullptr表示空指针

智能指针

最主要是为了解决内存释放问题。对于一个大型项目,我们在这里申请了一块内存,而在离这里很远的各个地方需要我们释放这块内存的时候,我们常常忘记这个操作,而且有时发现问题还很难排查出来。智能指针的目的就是让程序自动销毁这块内存,而不是靠程序员手动销毁。(未完待续)

打赏
  • © 2016-2021 留叶
  • Powered by Hexo Theme Ayer
    • PV:
    • UV:

请我喝杯咖啡吧~

支付宝
微信