# typedef
typedef 并不是简单的宏替代。
- 定义一种
类型的别名- 定义
struct结构体别名- 用 typedef 来定义与
平台无关的类型- 为
复杂的声明定义一个简单的别名,表示的是一个指向函数的指针
- 用
typedef可以定义各种类型别名,但不能定义变量 - 使用 typedef 便于
程序的通用 - 用
typedef只是将一个已经存在的类型用一个新的名称替代 typedef不能添加新类型
# typedef 和 #define 区别
typedef是一种类型别名,而#define只是宏定义,二者并不总是可以互换的。
# 比较函数
C++ 的比较函数适用于
整型字符串浮点数等多种类型。
# max
返回队列中的
最大值,参数两个参数,如果想要多个参数,使用大括号初始化列表容器的形式可以,但相比于直接两个两个比较比较耗时
#include <iostream> | |
#include <algorithm> | |
using namespace std; | |
int main(void) | |
{ | |
float a = 1.359; | |
float b = 1.823; | |
float c = 1.829; | |
auto result = max({ a, b,c }); | |
cout << result << endl; | |
return 0; | |
} |
# min
返回
队列中的最小值
# minmax
算法标头的库函数,用于查找
最小和最大值,它接受两个值并返回一对最小和最大值,该对中的第一个元素包含最小值,并且该对中的第二个元素包含最大值该函数包括
<algorithm>头文件,
#include <iostream> | |
#include <algorithm> | |
using namespace std; | |
int main(void) | |
{ | |
// 字符串类型同样应用于比较,会以 ASCII 码值进行对比 | |
int a = -10; | |
int b = -20; | |
auto result = minmax(a, b); | |
cout << "最小值" << result.first << endl; | |
cout << "最大值" << result.second << endl; | |
return 0; | |
} |
# 友元
在函数前加
friend友元
不是成员函数,但是它可以访问类中的私有和保护成员。提高了程序的
运行效率,但是破坏了类的封装和隐藏,使得非成员函数可以访问类的私有成员。
友元具有
不对称性,即 A 是 B 的友元,但 B 不一定是 A 的友元,单向的,不具有交换性友元关系
不具传递性友元关系
不能被继承
# main 参数
main 函数有三个参数,
argc,argv,envp
int main(int argc,char*argv[],char*envp[]) | |
{ | |
} | |
// **int argc: 存放了命令行参数的个数 | |
//char argv [] 是个字符串的数组,每个元素都是一个字符指针,指向一个字符串,即命令行中的每一个参数 | |
//char envp [] 也是一个字符串的数组,这个数组的每一个㢝是指向一个环境变量的字符指针 |
# 题

float,double,long double等类型不允许直接进行位与操作符如
float取地址(也是符号) 转换为unsigned int类型,再用取值操作符 (*), 编译器会识别为unsigned int类型使用
int short long移位时,最好加上unsigned,这样就是汇编中规律移位(即全部移位)加入不加 unsigned,正数全是规律
移位,负数左移保持符号位为1,右边补0,负数右移时保持符号位为1,左边补1,所有 - 1 无论怎么右移都是 - 1位与操作符的操作优先级小于 移位操作符,但移位操作符小于取地址操作符 (取值操作符 *・*)
# static
静态数据成员
类内定义,就必须在类外初始化。
特点:
- 所有成员都
共享数据成员,只有一份内存- 必须在
类外进行初始化
# 静态数据成员的内存?
存放在内存的全局区
# 基类的静态数据成员不能被继承
- 继承:继承是
一个类从另一个类获取成员变量和成员函数的过程 (子类继承父类)
继承特性:
继承访问不了父类私有属性- 但是
私有继承已经被继承,被编译器隐藏- 静态成员属性不会被继承 (属于全部对象)
- 创建子类时,
构造函数的调用,先父类后子类,析构时:先子类后父类构造函数,析构函数,赋值操作符不能被继承无论什么继承,子类
都可以访问基类中的公共保护成员,但子类对象就只能访问子类的公共成员在析构时:
- 当
释放子类的指针对象时,会调用子类和父类的析构函数- 当释放子类的指针对象时,只会调用
父类的析构函数
#include <iostream> | |
using namespace std; | |
class person// 父类 | |
{ | |
public: | |
person() { cout << "person的构造函数" << endl; } | |
~person() { cout << "person析构函数" << endl; } | |
}; | |
class son :public person | |
{ | |
public: | |
son() { cout << "son的构造函数" << endl; } | |
~son() { cout << "son的析构函数" << endl; } | |
}; | |
int main() | |
{ | |
son* s = new son;// 定义一个子类指针 | |
person* p = s;// 父类指针指向子类 | |
//delete s;// 释放子类内存 // 会调用子类和父类的析构函数 | |
delete p; // 释放父类 只会调用父类的析构函数 | |
return 0; | |
} |
# 据成员 为 什么必须 类外初始化
静态数据成员也属于静态变量,属于静态全局区,全局区的变量,随着程序生死。而对象不是全局静态区的,是有生命周期的。由于生命周期的不同,所以必须在类外初始化,来解决类的生命周期问题。
static加强了访问控制的全局变量,不被继承- 类和子类对象,
static变量占有一份内存
# 结构体内存
结构体内存规则
- 第一个成员在与结构体变量
偏移量为0的地址处其他成员变量要对齐到对齐数的整数倍的地址处对齐数=min (编译器默认的对齐数,该成员大小)- 结构体
总大小为最大对齐数(每个成员变量都有一个对齐数) 的整数倍- 如果
嵌套了结构体的情况,嵌套的结构体对齐到自己大的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(函嵌套结构体的对齐数) 的整数倍
# C 语言
# 变量类型
register:建议编译器将该变量放入CPU。
# 函数 类型缺省
- 返回值
- C 语言,如果函数
未指定返回值类型,则・默认为int - C++ 如果函数
没有返回值,默认类型必须指定为void
- C 语言,如果函数
- 参数列表
C语言,如果函数没有指定参数列表,返回值类型必须指定为 voidC++中,有严格的类型检测,没有参数列表的函数默认为void,不接受任意参数
- 缺省参数
C不支持C++支持,如果没有指定实参则使用缺省值,有则使用指定实参- 默认实参必须在
参数列表的结尾 - 默认参数只能出现在函数声明或者定义二选一中
- 缺省值
必须是常量或全局变量 - 缺省参数必须是
值传递或者常参传递
- 默认实参必须在
- 函数重载
- C: 不支持
- C++:支持
# 转义字符
\t表示横向指标\v表示竖向制表\b表示退格\r表示回车\f表示换页\?表示问号字符\0表示空字符(null)
# 指针大小
指针,在64bit的机器中是8字节,int 4字节
# 读取
getchar: 读取一个字符。%2d: 读取数字,限定两个字符,如读取的指针位置后面出现字母忽略掉,前面出现字母将全部忽略,指针移动到读取截止为止。
#define _CRT_SECURE_NO_WARNINGS | |
#include <stdio.h> | |
int main() | |
{ | |
char c1, c2; | |
int a1, a2; | |
c1 = getchar(); // 读取第一个字符 1 | |
scanf("%2d", &a1); // 读取宽度为两个,int 型,只读取 2 | |
c2 = getchar(); // 读取 a | |
scanf("%3d", &a2); // 宽度为 3,读物 345 | |
printf("%d,%d,%c,%c\n", a1, a2, c1, c2); | |
return 0; | |
} | |
/* | |
输入: 12a345b789 | |
输出: 2,345,1,a | |
*/ |
# 优先级
成员选择符
->的优先级比前置++,和后置++都要高
# 字符串未赋值部分
#define _CRT_SECURE_NO_WARNINGS | |
#include <stdio.h> | |
int main() | |
{ | |
int a[3][3] = { {1,2},{3,4},{5,6} }, i, j, s = 0; // 最后一个没有赋值的为 0 | |
for (i = 1; i < 3; i++) | |
{ | |
for (j = 0; j <= i; j++) | |
{ | |
s += a[i][j]; //a[2][2] = 0 | |
} | |
} | |
printf("%d\n", s++); | |
return 0; | |
} | |
/* | |
输出: 18 | |
*/ |
# 表达式等级类型
基本类型字符串
从低到高如下,运算的时候,从低转到高,表达式的类型会自动提升为参与表达式求值的最上级类。
charintlongfloatdouble
# 字符串操作
字符串时字符数组的一种形式,它以 "\0" 结尾
strcpy(): 复制字符串strcmp(): 比较字符串strlen(): 计算字符串的长度,遇到\0时结束计算,不算\0, 且从1开始计数。
// 将字符串 source 拷贝到字符串 destination 中 | |
// 函数返回 destination 字符串 | |
strcpy(char destination[], const char source[]); | |
// 将字符串 source 中前 numchars 个字符拷贝到字符串 destination 中 | |
// 注意 source 中 numchars 个字符将覆盖掉字符串 destination 中前 numchars 个字符 | |
// 函数返回 destination | |
strncpy(char destination[], const char source[], int numchars); | |
// 将字符串 source 接到字符串 target 的后面,要提前确保 taeget 有足够的空间 | |
// 函数返回 target | |
strcat(char target[], const char source[]); | |
// 将字符串 source 的前 nnumchars 个字符接到字符串 target 的后面 | |
strncat(char target[], const char source[], int numchars); | |
// 比较 first 是否大于 second,成功大于 0, | |
int strcmp(const char firststring[], const char secondstring); | |
// 统计长度 | |
// 统计字符串 string 中字符的个数 | |
strlen( const char string[]); |
# 参考资料
- C++ 继承
- typedef
- C 语言字符串操作总结大全
