C++实用经验(二)

博客围绕C++编程展开,介绍了const的使用,如函数声明、返回值声明、类成员函数中使用,建议用const常量替代#define;推荐用new/delete替代malloc/free,因其功能更全且安全;还讲解了sizeof用法、对象大小计算,最后提醒谨慎使用static,包括局部和全局静态变量及成员。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


声明:以下内容总结自《C++程序员不可不知的101条实用经验》

尽可能多地使用const

函数声明使用const

void func(const int *a) 等价于void func(int const *a)

const在*的左边,则指针所指的对象不可变;const在*的右边,则指针不可变。

函数返回值声明为const

A{}
A operator*(const A &a, const A &b);
A a, b, c
(a * b) = c; //不符合逻辑,通过const A operator*(const A &a, const A &b);防止函数调用表达式不能作为左值

const类成员函数

按位恒定规则:当且仅当一个成员函数对所有的数据成员都不做出改动时,才需要将此函数声明为const。这将使得错误检查更轻松
逻辑恒定规则:一个const成员函数可能对其调用的对象内部做出改动,但仅仅以客户端无法察觉的方式进行,使用mutable数据成员可实现这一目标

尽量用const常量代替#define定义常量

  1. #define没有类型检查,可能有边际效应。而const有类型检查
  2. #define定义的常量在内存中有多个拷贝,而const常量只有一份拷贝,所以使用const常量可以节省内存

尽量用new/delete替代malloc/free

  1. new/delete在管理内存时会调用类的构造函数和析构函数,而malloc/free仅仅实现了内存的分配和释放
  2. new/delete是运算符,而malloc/free是C语言标准库函数
  3. 通过new创建的对象具有类型,而malloc返回值类型为void*,需要进行强制类型转换
  4. new申请内存失败会调用new_handler处理函数,而malloc申请内存失败仅仅返回NULL,不进行其他任何善后处理
  5. new/delete具备malloc/free的所有功能,还具有更好的安全特性,不要混用new和malloc,尽量使用new
  6. 调用new时使用了[],则对应调用delete时也使用[]
string *s = new string();
string *sarr = new string[10];
//......
delete s;
delete []sarr;

sizeof和对象大小

用法

  1. sizeof不是函数,不是一元操作符,像一个特殊的宏,在编译阶段求值
  2. 任何类型的指针,sizeof结果都是4(32位)或8(64位)
  3. 函数类型以其返回值的类型作为自身类型,sizeof(func())的值为func()返回值类型大小
  4. 无法对函数指针使用sizeof
int func();
sizeof(func()); //4
sizeof(func); //error
  1. 字符数组表示字符串时,末尾会自动加’\0’,所以sizeof时会在字符串中字符个数的基础上加1
  2. C语言中多维数组的实现是通过一维数组实现的,所以数组的大小是各维度的乘积乘以数组元素大小
  3. 向函数形参传递数组,数组指针会退化为普通指针,失去原有数组指针的特性
char *a = "abc"; //sizeof(a)为3+1=4
char b[] = {'a', 'b', 'c'}; //sizeof(b)为3
int c[20] = {1,2}; /sizeof(c)为20 * 4=80
char d[2][3] = {"aa", "bb"}; //sizeof(d)为6,sizeof(*d)为3
  1. 对一个空的结构体或类进行sizeof运算,结果为1,不为0,这是编译器为了保证空结构体和空类存在而专门分配这一个字节
  2. 类的大小
    1)没有继承和static成员的类:需要内存对齐,和结构体大小计算方式一样,空类占用一个字节。类的成员函数为所有类对象共享,存储在代码段,所以不占用对象空间
    2)包含继承和static成员变量的类:在单继承的情况下,只要类中有virtual函数,就会有一个指向虚函数表的指针。static成员分配在全局区,为类的所有对象共享,sizeof不考虑静态成员

谨慎使用static

静态局部变量

  1. 存储在全局静态存储区,在初次运行进行初始化,编译器可自动初始化为0
  2. 记忆性:前后两次函数调用时,第二次调用进入 时,能保持第一次调用退出时的值。
  3. 全局性:生存周期与全局变量、程序相同
  4. 记忆性破坏了程序的不可重复性,导致不同时刻的运行结果可能不同
  5. static具有全局唯一性,每次调用都指向同一块内存,造成不可重入性
  6. 局部static变量导致函数具有线程不安全性,即多个线程调用同一函数时,可能出现读取脏数据等情况

静态全局变量

静态全局变量和全局函数不能被其他文件访问的,用于限定作用域

  1. 静态成员变量
    1)遵从public、protected、private访问规则
    2)初始化格式:<数据类型> <类名>::<静态成员变量>=<值>
    3)多个同类对象共享静态成员变量,在程序中只有一份拷贝
  2. 静态成员函数
    1)没有隐含的this指针,效率比普通函数高
    2)不可访问类的非静态成员,只能访问静态成员
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值