一.回忆一下C++
using可以代替typedef
using intvec = std::vector<int>;
const int& fun(int& a); //修饰返回值
int& fun(const int& a); //修饰形参
int& fun(int& a) const{} //const成员函数
char实质是一个字节的整形
signed表示有符号,unsigned表示无符号
修饰符 signed、unsigned、long 和 short 可应用于整型,signed 和 unsigned 可应用于字符型,long 可应用于双精度型。
修饰符 signed 和 unsigned 也可以作为 long 或 short 修饰符的前缀。例如:unsigned long int。
也可以只写单词 unsigned、short 或 long,int 是隐含的.
修饰符 volatile 告诉编译器不需要优化volatile声明的变量,让程序可以直接从内存中读取变量。对于一般的变量编译器会对变量进行优化,将内存中的变量值放在寄存器中以加快读写效率。
由 restrict 修饰的指针是唯一一种访问它所指向的对象的方式
extern 用于声明一个全局变量或函数,用以支持在当前文件(或者引用了这个文件的其他文件)中可以使用,而变量或者函数真正的定义可以在任何地方.
使用 thread_local 说明符声明的变量仅可在它在其上创建的线程上访问。 变量在创建线程时创建,并在销毁线程时销毁。 每个线程都有其自己的变量副本。
thread_local int x; // 命名空间下的全局变量
class X
{
static thread_local std::string s; // 类的static成员变量
};
static thread_local std::string X::s; // X::s 是需要定义的
void foo()
{
thread_local std::vector<int> v; // 本地变量
^ 异或运算
~ 按位取反,包括符号位
<< 左移若干位
>>右移若干位
A = 0011 1100
// ~A : 1100 0011
//A << 2 : 1111 0000
//A >> 2 : 0000 1111
位运算也支持和赋值结合
A <<= 2
lambda表达式 capture->return-type{body}
[] // 沒有定义任何变量。使用未定义变量会引发错误。
[x, &y] // x以传值方式传入(默认),y以引用方式传入。
[&] // 任何被使用到的外部变量都隐式地以引用方式加以引用。
[=] // 任何被使用到的外部变量都隐式地以传值方式加以引用。
[&, x] // x显式地以传值方式加以引用。其余变量以引用方式加以引用。
[=, &z] // z显式地以引用方式加以引用。其余变量以传值方式加以引用。
[](int x, int y){ return x < y ; }
[](int x, int y) -> int { int z = x + y; return z + x; }
[this]() { this->someFunc(); }();
引用经常被理解为地址,与指针的区别:
不存在空引用。引用必须连接到一块合法的内存。
一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。
引用必须在创建时被初始化。指针可以在任何时间被初始化。
//这个函数需要一个int型的引用为参数
void swap(int& x);
int i;
//创建了一个int型引用
int& r = i;
//返回一个double类型引用
double& setValues(int i)
typedef定义时,Books可以取代struct Books
typedef struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
}Books;
变量和指针访问结构体或对象成员的区别:变量用.指针用->
Books Book1; //定义结构体
struct Books *struct_pointer; //定义指针
struct_pointer = &Book1; //指针赋值
struct_pointer->title; //指针访问结构体成员
范围解析运算符 ::
用于在类的定义之外添加成员函数
//表示给Box添加一个成员函数
double Box::getVolume(void)
{
return length * breadth * height;
}
构造函数的初始化列表
Line::Line( double len): length(len)
{
//do something
}
//length是Line的成员变量,这个函数其实就相当于下面
Line::Line( double len)
{
length = len;
//do something
}
析构函数
Line::~Line(void)
{
// do something
}
声明函数,可以先不提供实现;
其中Line( const Line &obj);是拷贝构造函数,相当于objc的copy
class Line
{
public:
Line( int len ); // 简单的构造函数
Line( const Line &obj); // 拷贝构造函数
~Line(); // 析构函数
};
使用friend声明友元函数或友元类,他们可以访问类的private和protected成员
注意:1.printWidth() 不是任何类的成员函数
2.友元函数不能使用this
class Box
{
double width;
public:
friend void printWidth( Box box ); //声明友元函数
void setWidth( double wid );
};
void printWidth( Box box )
{
/* 因为 printWidth() 是 Box 的友元,它可以直接访问该类的任何成员 */
cout << "Width of box : " << box.width <<endl;
}
//声明友元类
class Tex
{
friend class Box;
Int num;
};
使用inline声明内联函数,如果一个函数是内联的,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方,类似于宏替换,以空间换时间.
1.在内联函数内不允许使用循环语句和开关语句;
2.内联函数的定义必须出现在内联函数第一次调用之前;
3.在类定义的{}内定义的函数默认就是内联函数。
//这是一个全局的内联函数
inline int Max(int x, int y)
{
return (x > y)? x : y;
}
在C++中重载指的是同样的函数名有着不一样的参数列表和返回值
void print(int i) {
cout << "整数为: " << i << endl;
}
void print(double f) {
cout << "浮点数为: " << f << endl;
}
void print(char c[]) {
cout << "字符串为: " << c << endl;
}
用virtual声明虚函数,只有virtual修饰的函数才能实现多态(在派生类中重写)
抽象类也是类似的用法
virtual int area()
{
cout << "Parent class area :" <<endl;
return 0;
}
//纯虚函数,表示不存在默认的实现
virtual int area() = 0;
函数使用泛型:template <typename type>
template <typename T>
inline T const& Max (T const& a, T const& b)
{
return a < b ? b:a;
}
类使用泛型:template <class type>
//声明类
template <class T>
class Stack {
void push(T const&); // 入栈
};
//实现方法
template <class T>
void Stack<T>::push (T const& elem)
{
elems.push_back(elem);
}
//使用类
Stack<int> intStack; // int 类型的栈
intStack.push(7);
= delete
表示删除这个方法,常用的方式比如禁止拷贝,禁止运算符重载
MyClass(const MyClass&) = delete;
MyClass(MyClass&&) = delete;
void operator=(const MyClass&) = delete;
void operator=(MyClass&&) = delete;
二.信号处理
信号是由操作系统传给进程的中断,会提早终止一个程序;
有些信号不能被程序捕获,但是下表所列信号可以在程序中捕获,并可以基于信号采取适当的动作。这些信号是定义在 C++ 头文件 <csignal> 中,在iOS调试中经常能够看到.
SIGABRT 程序的异常终止,如调用 abort。
SIGFPE 错误的算术运算,比如除以零或导致溢出的操作。
SIGILL 检测非法指令。
SIGINT 程序终止(interrupt)信号。
SIGSEGV 非法访问内存。
SIGTERM 发送到程序的终止请求。
C++ 信号处理库提供了 signal 函数,用来捕获突发事件。以下是 signal() 函数的语法:
void (*signal (int sig, void (*func)(int)))(int);
//可以简化成这样,第一个参数是一个整数,代表了信号的编号;第二个参数是一个函数指针,并且把编号传进去
signal(registered signal, signal handler)
使用案例
void signalHandler( int signum )
{
cout << "Interrupt signal (" << signum << ") received.\n";
// 清理并关闭
// 终止程序
exit(signum);
}
int main ()
{
// 注册信号 SIGINT 和信号处理程序
signal(SIGINT, signalHandler);
while(1){
cout << "Going to sleep...." << endl;
sleep(1);
}
return 0;
}
int raise (signal sig)可以用于生成信号,参数是SIGINT、SIGABRT、SIGFPE、SIGILL、SIGSEGV、SIGTERM、SIGHUP其中之一
void signalHandler( int signum )
{
cout << "Interrupt signal (" << signum << ") received.\n";
// 清理并关闭
// 终止程序
exit(signum);
}
int main ()
{
int i = 0;
// 注册信号 SIGINT 和信号处理程序
signal(SIGINT, signalHandler);
while(++i){
cout << "Going to sleep...." << endl;
if( i == 3 ){
raise( SIGINT);
}
sleep(1);
}
return 0;
}
三:C++的多线程
#include <pthread.h>
//pthread_create (thread, attr, start_routine, arg)
thread 线程指针
attr 用来设置线程属性,可以使用默认值 NULL。
start_routine 线程执行的函数
arg 运行函数的参数。它必须通过把引用作为指针强制转换为 void 类型进行传递。如果没有传递参数,则使用 NULL。
线程创建成功时,pthread_create返回0;
//终止线程
pthread_exit (status)
案例
#include <iostream>
// 必须的头文件
#include <pthread.h>
using namespace std;
#define NUM_THREADS 5
// 线程的运行函数
void* say_hello(void* args)
{
cout << "Hello Runoob!" << endl;
return 0;
}
int main()
{
// 定义线程的 id 变量,多个变量使用数组
pthread_t tids[NUM_THREADS];
for(int i = 0; i < NUM_THREADS; ++i)
{
//参数依次是:创建的线程id,线程参数,调用的函数,传入的函数参数
int ret = pthread_create(&tids[i], NULL, say_hello, NULL);
if (ret != 0)
{
cout << "pthread_create error: error_code=" << ret << endl;
}
}
//等各个线程退出后,进程才结束,否则进程强制结束了,线程可能还没反应过来;
pthread_exit(NULL);
}
std::thread
C++ 11 之后添加了新的标准线程库 std::thread,std::thread 在 <thread> 头文件中声明,因此使用 std::thread 时需要包含 在 <thread> 头文件
#include<thread>
std::thread thread_object(callable)
其中callable可以是函数指针,函数对象,lambda 表达式都行.
案例
void testfun1() {
std::cout <<"test threadid is :" << this_thread::get_id() << std::endl;
}
void testfun2(int num) {
std::cout <<"test threadid is :" << this_thread::get_id() << std::endl;
}
void testfun3(int& num) {
std::cout <<"test threadid is :" << this_thread::get_id() << std::endl;
}
//使用
std::thread th(testfun1); //创建线程
int testnum = 1;
std::thread th2(testfun2, testnum); //带参数,参数值传递
std::thread th3(testfun3, std::ref(testnum)); //带参数,参数引用传递
网友评论