前言
可能有很多错误,感谢指出
I’m so much older then, I’ younger than that now. —Bob Dylan
C++
基础语法
const
分为修饰变量、指针、引用,简单记忆为const后面修饰的值不可改变
const int A;
const int* A;
const int& A;
int* const A;
const int* const A;
void function1(const int A);
void function2(const int* A);
void function3(int* const A);
void function4(const int& A);
const int function5();
const int *function6();
int * const function7();
static
- 变量
局部变量: 普通局部变量储存在栈空间,使用完立刻释放。编译器一般不对局部变量初始化,除非显示赋值。 静态局部变量使用static关键字修饰,初始值为0。且静态局部变量存储于进程的全局数据区,函数返回也不会改变值
如下面demo
void func() {
int n = 10;
printf("n = %d\n", n);
n++;
printf("n++ = %d\n", n);
}
void func_static() {
static int n = 10;
printf("static n = %d\n", n);
n++;
printf("n++ = %d\n", n);
}
int main() {
func();
printf("\n\n\n");
func_static();
printf("\n\n\n");
func();
printf("\n\n\n");
func_static();
}
结果如下
untitled1 % ./a.out
n = 10
n++ = 11
static n = 10
n++ = 11
n = 10
可见静态局部变量作用类似于全局变量
全局变量: 全局变量定义于函数体外部,在全局数据区分配空间,编译器会自动初始化。 普通全局变量对整个工程可见,其他文件extern外部声明以后可以使用(其他文件不能再定义相同名字的全局变量,否则编译器会认为是同一个变量) 静态全局变量仅对当前文件可见,其他文件不可访问且可定义同名变量。 有效降低程序模块间的耦合,避免不同文件变量名冲突
- 函数
静态函数就是在返回类型前加上static,类似于静态全局变量,特性如下 静态函数只能在声明它的文件中可能,其他文件不能引用该函数 不同文件可以使用同名静态函数(注意这里和静态全局变量的区别,静态全局变量和同名普通全局变量可以共存)
非静态函数可以被其他文件直接引用,甚至不需要extern声明 3. 面向对象 静态数据成员: 存储在全局数据区,静态数据成员在定义是分配存储空间,无论定义了多少个对象都只有一个拷贝
静态成员函数: 静态成员函数没有this指针,无法访问类对象的非静态成员函数与非静态成员变量,只能调用静态成员变量与函数 出现在类外的函数定义不能指定关键字static
this指针
- 定义:
C++中,每一个对象可以通过this指针访问自己的地址,this指针是所有成员函数的隐含参数,用于指向调用对象 - this只能在成员函数中使用(友元函数,全局函数不是成员函数)
- this不能在静态函数中使用,静态函数在类定义时创建,不属于具体对象
inline内联函数
定义: 在函数声明和定义中,函数返回类型前加上关键字inline,将函数指定为内联函数,解决一些频繁调用的函数大量消耗栈空间(栈内存)的问题。
特征:
- 相当于把内联函数的内容写到调用内联函数内,不用执行进入函数的步骤,直接执行函数体
- 类似宏,但是比宏多了类型检查
- 一般不内联包含循环、递归、switch等复杂操作的内联函数
- 类声明中定义的函数,除了虚函数,其他函数都会自动隐式为内联函数,类外声明的函数则需要显式定义
extern
定义: extern放在变量和函数声明前,表示该变量或者函数在别的文件中已经定义,提示编译器在编译时要从别的文件中寻找。
- 声明外部变量:用关键字extern对变量外部声明,表示该变量是个已经被定义的外部变量
- 声明外部函数:函数声明带不带extern没有,但是可以使用extern来代替include “*.h”
extern “C”
- 比起C语言,编译C++代码时会将函数名拼上参数类型,因此C++支持重载
- 为了更好的支持C++中调用C语言代码,我们加入了 extern “C”
- 被 extern"C" 修饰的变量和函数是按照C语言方式编译和链接的,可以避免C++因符号修饰导致代码不能和C豫园库中函数进行链接的问题
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
为什么复制构造函数的参数需要加const和引用?
(1) 为什么要用引用: 比如对于下面的代码,执行b.my_A(a),传参因为是传值,所以会调用拷贝构造函数,A tmp = a。如果拷贝构造函数页数传值,那么还要调用拷贝构造函数执行 A tmp = a,这样就递归调用下去了。
class A {
public:
A():num(0){}
A(int n): num(n){}
A(const A& a) {
num = a.num;
}
A& operator = (const A& a) {
num = a.num;
return *this;
}
void print() {
cout << num << endl;
}
void my_A(A a) {
a.print();
}
private:
int num;
};
int main() {
A a(1);
A b(2);
b.my_A(a);
}
(2) 为什么要用const: 为了防止函数执行过程中对被引用参数的修改
STL
string
-
C语言中字符串只能删除,不能增加,而且通过 char* str = “hello”; 方式定义的字符串指针会被视为常量,字符串管理比较繁琐,因此需要引入 STL的string管理字符串 -
string分配的字符串空间在堆上,每次往字符串尾部新增字符肯定要增加空间,但是相邻内存可能找不到,因此需要分配一个更大的空间块,并将原来的字符串移过去 -
string类的简单实现
class String {
public:
String(const char* str = NULL);
String(const String& other);
~ String();
String &operator = (const String& other);
String &operator + (const String& other);
bool operator == (const String &other);
int getLength();
private:
char*m_data;
};
String::String(const char* str) {
if(str == NULL) {
m_data = new char[1];
*m_data = '\0';
} else {
int length = strlen(str);
m_data = new char[length + 1];
strcpy(m_data, str);
}
}
String::~String() {
if(m_data) {
delete[] m_data;
m_data = 0;
}
}
String::String(const String &other) {
if(!other.m_data) {
m_data = 0;
} else {
m_data = new char[strlen(other.m_data) + 1];
strcpy(m_data, other.m_data);
}
}
String & String::operator=(const String &other) {
if(this != &other) {
delete[] m_data;
if(!other.m_data) {
m_data = 0;
} else {
m_data = new char[strlen(other.m_data) + 1];
strcpy(m_data, other.m_data);
}
}
return *this;
}
String & String::operator+(const String &other) {
String newString;
if(!other.m_data) {
newString = *this;
} else if(!m_data) {
newString = other;
} else {
newString.m_data = new char[strlen(m_data) + strlen(other.m_data) + 1];
strcpy(newString.m_data, m_data);
strcat(newString.m_data, other.m_data);
}
return newString;
}
bool String::operator==(const String &other) {
if(strlen(m_data) != strlen(other.m_data)) {
return false;
} else {
return strcmp(m_data, other.m_data) == 0;
}
}
int String::getLength() {
return strlen(m_data);
}
vector
计算机网络
操作系统
数据库
链接装载与库
项目
Go
算法
|