C++学习笔记
Posted 木大白易
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++学习笔记相关的知识,希望对你有一定的参考价值。
本文来自菜鸟教程的总结。
指针
指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。
一般形式为type *name
type为指针的基类型,name为指针变量的名字,*用来指示这个变量是指针。
int var = 20; // 实际变量的声明
int *ip; // 指针变量的声明
ip = &var; // 在指针变量中存储 var 的地址
//打印相关变量的值
//var----->20 表示变量var
//ip----->0xbfc601ac 表示指向变量var的内存地址
//*ip----->20 表示指向变量var内存地址上的值
NULL指针
在指针初始化或者手动销毁的时候,通常赋值为NULL 。
指向指针的指针
指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链。
指针的指针就是将指针的地址存放在另一个指针里面。
int var;
int *ptr;
int **pptr;
var = 3000;
// 获取 var 的地址
ptr = &var;
// 使用运算符 & 获取 ptr 的地址
pptr = &ptr;
//那么var,*ptr,**pptr的值是一样的,都是3000
传递指针给函数
传递指针给函数,只需要声明函数参数为指针类型。
void passPtr(int *p);//声明函数
void passPtr(int *p){//函数定义
*p = 2021;
return;
}
int main(){
int a = 2020;
passPtr(&a); //函数将a的值改为了2021
cout << a << endl;
return 0;
}
引用
注意它和指针的区别:
- 不存在空引用。引用必须连接到一块合法的内存。
- 一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。
- 引用必须在创建时被初始化。指针可以在任何时间被初始化。
//引用
int i = 5;//声明简单的变量
int& r = i;//声明引用变量
cout << i << endl;
cout << r << endl;
//i和r打印的值都是5,因为都是一块内存
数据结构
//声明一个结构体类型 User
struct User{
char name[20];
int age;
};
User zhangsan;//定义结构体类型为User的变量zhangsan
//赋值
strcpy(zhangsan.name, "张三");
zhangsan.age = 18;
类和对象
跟java类似
class User{
private: //访问修饰符后边要有一个冒号
string name;
int age;
public:
void setName(string p_name){ //类成员函数
name = p_name;
}
string getName(){
return name;
}
}; //这里注意要有一个分号
int main(){
User zhangsan;
zhangsan.setName("张三");
cout << "zhangsan的名字:" << zhangsan.getName() << endl;
return 0;
}
类成员函数除了可以在类内部定义,也可以在外部:
//在类内部声明,在类外部定义
void User::setName(string p_name){ //类名::成员函数名
name = p_name;
}
构造函数和析构函数
当一个对象被创建的时候,构造函数被执行。
析构函数在每次删除对象时执行。
class User{
private: //访问修饰符后边要有一个冒号
string name;
int age;
public:
User(){} //无参构造函数
User(int p_Age){ //有参构造函数
age = p_Age;
}
~User(){ //析构函数
cout << "对象销毁" << endl;
}
};
静态成员和静态函数
使用static关键字修饰
调用的时候:
类名::静态变量;
类名::静态函数();
继承
子类可以访问父类所有非私有的成员和函数。
class Animal{
public:
void eat(){}
void sleep(){}
private:
void mySecret(){}
};
class Dog : public Animal{ //继承 访问修饰符默认为private
public:
void bark(){}
};
另外,继承类型由访问修饰符控制,默认为private。
public:父类public,protected成员和函数仍为子类的,类型不变。private类型不能由子类直接访问。
protected:父类public,protected成员和函数为子类的protected类型。
private:父类public,protected成员和函数为子类的private类型。子类不能直接访问。
函数重载和运算符重载
函数重载:可以声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同。与返回值无关。
运算符重载:重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。
User operator+(const User&);//对加号+重载,将两个User对象相加并返回一个User对象
多态
当一个子类继承父类,要重写父类某一个函数时,父类中函数要使用virtual关键字修饰,否则子类调用函数被编译器设置为父类中的版本,这就是所谓的静态多态。
在父类中使用关键字virtual声明的函数,被称之为虚函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。这种操作被称为动态链接。
如果在父类中定义虚函数,但是又不想给具体的函数实现,使用=0表示函数没有主体,这样的虚函数被称之为纯虚函数。
class User{
virtual string work() = 0;//纯虚函数
}
如果类中至少有一个函数被声明为纯虚函数,则这个类就是抽象类。比如上边的User类现在就是一个抽象类。
抽象类不能被实例化对象,它只能被作为接口使用。所有继承抽象类的子类如果要被实例化,则必须要实现抽象类中的所有纯虚函数。
动态内存
new,delete
int* p = NULL; //声明变量
p = new int; //在堆中分配内存
*p = 2021; //赋值
delete p; //释放内存
它与int p = 2021的区别就是这种是在栈内存中的,使用完会自动释放。而动态分配内存是在堆中,需要手动释放。
数组的动态分配
// 动态分配,数组长度为 m
int *array=new int [m];
//释放内存
delete [] array;
模板
类似于java的泛型。
函数模板
template <typename type> ret-type func-name(parameter list)
{
// 函数的主体
}
template <typename T> T max(T a, T b){
}
类模板
template <class type> class class-name {
//类主体。。。
}
template <class T> class Stack {
private:
vector<T> elems; // 元素
public:
void push(T const&); // 入栈
void pop(); // 出栈
T top() const; // 返回栈顶元素
bool empty() const{ // 如果为空则返回真。
return elems.empty();
} };
预处理器
预处理器是一些指令,指示编译器在实际编译之前所需完成的预处理。
所有的预处理器指令都是以#开头,只有空格字符可以出现在预处理指令之前。预处理指令不是 C++ 语句,所以它们不会以分号;结尾。
#define
#define 预处理指令用于创建符号常量。该符号常量通常称为宏。
#define PI 3.14
//这里注意后边的括号
#define MIN(a,b) (a<b ? a : b)
条件编译
条件预处理器的结构与 if 选择结构很像。
#if 0表示注释掉代码,不进行编译。
#define DEBUG
int main ()
{
#ifdef DEBUG
cerr <<"Trace: Inside main function" << endl;
#endif
#if 0
/* 这是注释部分 */
cout << MKSTR(HELLO C++) << endl;
#endif
return 0;
}
预定义宏
- LINE:当前行号
- FILE:当前文件名
- DATE:当前月 日 年的日期
- TIME:当前
h:m:s
的时间
多线程
创建线程
#include <pthread.h>
pthread_create (thread, attr, start_routine, arg)
pthread_create 创建一个新的线程,并让它可执行。
- thread:线程指针,类型为pthread_t
- attr:设置线程属性,可以为NULL
- start_routine:函数指针,在线程被创建时调用(比如void *startFunc(void *arg))
- arg:上边运行函数的参数,用于向线程传递参数
终止线程
#include <pthread.h>
pthread_exit (status)
pthread_exit 用于显式地退出一个线程。
连接和分离线程
pthread_join (threadid, status)
pthread_detach (threadid)
pthread_join() 子程序阻碍调用程序,直到指定的 threadid 线程终止为止。当创建一个线程时,它的某个属性会定义它是否是可连接的(joinable)或可分离的(detached)。只有创建时定义为可连接的线程才可以被连接。如果线程创建时被定义为可分离的,则它永远也不能被连接。
如果不想被阻塞,可以在子线程中加入代码 pthread_detach(pthread_self())或者父线程调用 pthread_detach(thread_id)(非阻塞,可立即返回),这将该子线程的状态设置为detached,则该线程运行结束后会自动释放所有资源。
以上是关于C++学习笔记的主要内容,如果未能解决你的问题,请参考以下文章