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[] 也是一个字符串的数组,这个数组的每一个㢝是指向一个环境变量的字符指针题
(图片 image-20230716092743942.png 未随仓库迁移,原引用路径已失效)
-
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[]);