C++中的类
类
C++中可以使用struct和class来定义一个类。
struct Person
{
int age;
void run()
{
// ...
}
};
class Person1
{
int age;
void run()
{
// ...
}
};
int main()
{
// 创建对象
Person p1;
Person1 p2;
p1.age = 10;
p2.age = 20; // 错误,因为属性权限是private
// 通过指针访问
Person *p3 = &p1;
p3->age = 20;
return 0;
}
C++对象占用的内存空间大小取决于成员变量占用内存空间的总和。成员函数只有一份内存,而且这份内存,不属于对象。
C++对象 ...
C++内存空间的布局
每个应用都有自己独立的内存空间,其内存空间一般都有:代码段(代码区)、数据段(全局区)、栈空间、堆空间。
代码段(代码区)
用于存放代码。
数据段(全局区)
用于存放全局变量等。
栈空间
每调用一个函数,就会给它分配一段连续的栈空间,等函数调用完后,就会回收空间。
堆空间
在程序运行过程,为了能够自由控制内存的生命周期、大小,会经常使用堆空间的内存。
堆空间的申请和释放
如果内存够用,会分配一块连续的内存空间出来。
malloc和free
void * malloc(size_t size)
void free(void *)
int main()
{
int *p = (int *)malloc(4);
*p = 4;
free(p);
char *chs = (char *)malloc(4);
for ( int i = 0; i < 4; i++ )
*(chs + i) = (char) ('A' + i);
// chs[i] = i + 1;
...
C++ const与引用
const
被const修饰的变量不可被修改,在定义的时候,就必须赋值。
如果修改的类、结构体(的指针),其成员已不可以被修改。
struct Date
{
int year;
int month;
int day;
};
int main()
{
const int a = 1;
a = 2; // 错误
const Date d = { 2021, 7, 3 };
Date d1 = { 2021, 8, 3 };
d = d1; // 错误
d.year = 2015; // 错误
Date *p = &d1; // 如果改成 Date *p = &d1,下面3行操作全部都会报错
p->year = 2015; // d1.year: 2015;
(*p).month = 5; // d1.month: 5;
*p = d; // p->year: ...
C++内联函数与表达式
内联函数(inline function)
使用inline修饰函数的声明或实现,可以使其变成内联函数。
与宏的区别
#define add(a, b) a + b
inline int f_add(int a, int b)
{
return a + b;
}
int main()
{
int a = 10;
int c = add(1, 2); // c = 3
int d = add(++a); // d = 24。 int d = ++a + ++a;
int e = f_add(++a); // e = 22;
return 0;
}
特点
编译器会将函数调用展开成函数体代码。
会增大代码的体积。
可以减少调用函数时的开销。开栈和回收栈空间的操作。
内联函数有函数最基本的特性,比如语法检测,传参等。
注意
尽量不要内联超过10行的函数。
有些函数即使声明为inline,也不一定会被编译器内联,比如递归。
inline func();
inline int sum( ...
C、C++混合开发
常用关键字
extern "C"
#ifndef
#ifdef
#define
#endif
#pragma once
__cplusplus
extern “C”
被extern "C"修饰的代码会按照C语言的方式去编译。
extern "C" void func(int a)
{
}
extern "C" void func(int a, int b)
{
}
extern "C"
{
void func(int a, int b)
{
}
void func(int a)
{
}
}
用途:C、C++混合开发。
// math.h
#ifndef __MATH_H // 防止重复包含,如果没有定义 MATH_H 这个宏
#define __MATH_H // 在这里就定义,下次在#include "math.h& ...
汇编
汇编语言的种类
8086汇编(16bit)。
x86汇编(32bit)。
x64汇编(64bit)。
ARM汇编(嵌入式、移动设备)。
…
x64汇编根据编译器的不同,有2种书写格式:
Intel。
AT&T。
汇编语言不区分大小写。
x64汇编-寄存器
通常,CPU会将内存中的数据存储到寄存器中,然后再对寄存器中的数据进行运算。
假设内存中有块红色内存空间的值是3,现在想把它的值加1,并将结果存储到蓝色内存空间。
CPU首先将红色内存空间的值放到EXA寄存器中:mov eax, 红色内存空间。
让EAX寄存器与1相加:add eax, 1。
赋值给蓝色内存空间:mov 蓝色内存空间, eax。
对应代码大概是这样子:
int a = 1;
int b = a + 1;
通用寄存器
64bit:RAX、RBX、RCX、RDX。
32bit:EAX、EBX、ECX、EDX。
16bit:AX、BX、CX、DX。
cpu会将寄存器一半(低位)拿出来,兼容以前的寄存器。以此类推。
比如,64位的寄存器,会将0-31位拿出来兼容32位。
如图,EAX就存在RAX里 ...
C++逐行读取文件
使用ifstream。
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream ifs("test.txt");
// 是否读取成功
if ( !ifs )
{
cout << "读取失败" << endl;
return 0;
}
string line;
while ( getline(ifs, line) )
cout << line << endl;
return 0;
}
C++默认参数
默认参数就是给函数的形参一个缺省值,在调用的时候,可以根据实际情况省略实参。
注意
C++有默认参数,C是没有的。
如果函数同时有声明、实现,默认参数只能放在函数声明中。
默认参数的值可以的常量、全局符号(全局变量、函数名)。
int f(int a, int b)
{
return a + b;
}
int test(int a, int b = 10, int (*func)(int, int) = f)
{
return func(a, b);
}
只能从右往左给。
这样是正确的。
int test(int a, int b = 10, int c = 20)
{
return a + b + c;
}
这样是不正确的。
int test(int a, int b = 10, int c)
{
return a + b +c;
}
调用函数的时候,是无法像Python一样指定某个参数的值的,只能从左往右赋值。
默认参数和函数重载一起使用时,可 ...
C++函数重载
函数重载英文:Overload。
函数名字一样,参数个数不同,参数类型不同,参数顺序不同。
注意
C++有函数重载,C没有。
函数重载和返回类型无关。
调用函数时,实参的隐式类型转换可能会产生二义性。
本质
函数重载采用了name mangling或叫name decoration技术。
就是编译器对符号名(比如函数名)进行了改编、修饰,有些地方翻译为命名倾轧
重载时,编译器会生成多个不同的函数名,不同的编译器,有不同的生成规则。
Debian查看当前系统的版本信息
这里介绍两种方法
1. 查看/etc/issue文件
最简单的就是查看/etc/issue文件了。
# cat /etc/issue
Debian GNU/Linux 10 \n \l
如果要查看Debian的小版本号,可以查看/etc/debian_version文件。
# cat /etc/debian_version
10.9
2. 查看/etc/os-release文件
这个文件有更详细的版本信息。
# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/suppo ...
