C++

C++

发展

C 面像过程 ->1979 C 带类的C->1983 C++面像对象OOP->C++98 STL标准库-> 2011 C++11 Boost库 -> 14->17->20 每三年一版
三大特性:封装 继承 多态
强大的抽象封装能力
高性能
低功耗
语法相对复杂,学习曲线较陡
注意开发规范,否则代码难维护
开发成本高

.cpp编译 -> .asm -> 链接.obj -> .exe
qt自带gcc windows
xocde glang
g++
源码.c -E预处理.i -S编译.s -c汇编.o gcc 链接 -o 指定输出文件名
一步完成 gcc -o a.exe a.c

教程

  1. https://www.runoob.com/cplusplus/cpp-tutorial.html
    char 1 -128~127|0~255
    shor int 2 -32768~32767|0-65535
    long int 4 -21247483648~2147483647|0~4294967295
    int 4 -21247483648~2147483647|0~4294967295
    float 4 3.4e+/-38
    double 8 1.7e+/-308
    long double 8 1.7e+/-308
    boolr 1 true/false
    wchart_t 2

C++ keywords: https://en.cppreference.com/w/cpp/keyword
定义常量 #define(宏替换) const(建议)
前缀0x十六进制 0八进制 L’x’宽字符 后缀U符号 L long
\转义字符 \ \’ \” \? \a 警报铃声 \b 退格键 \f 换页符 \n 换行符 \r 回车 \t 水平制表符 \v 垂直制表符 \ooo 一到三位的八进制数 \xhh… 一个或多个数字十六进制数

逻辑运算&& || ! 位运算 & ^ | ~ << >>(对有符号的数,尽可能不要使用右移运算)
sizeof(), Condition ? X:Y, , . , ->, Cast(不建议使用),&(取变量地址),*(指向变量)

补码(两种计算方式) 大小端

注释: // /* */

typedef struct{
short Sunday=0;
….
}Week;

默认成员权限公开的
struct A{
}
默认成员权限私有的
class Trace{
public:
virtual double Area() const=0; //多态,子类方法实现不一致时加virtual,const=0表示简单实现,虚的
}
typedef enum __COLOR{
RED,
}color;

union Score{
}
定义常量 #define const
声明 enum color{red,gree}; color color1;

注意结构体数据对齐问题32位CPU4字节
连续分配修改编译选项:
V C++: #pragma pack(n)
g++: attribute(aligned(n)) attribute(packed)

int arr[2] = {1,2}; arr[2] =5;int * p =arr;*(p+2)=5;
int len = sizeof(arr)/sizeof(arr[0]);
差一错误, (]左闭右开,
循环时尽可能满足”空间局部性”
新型数组vector(面向对象方式的动态数组)
字符串是以空字符(‘\0′)结束的字符数组,在声明时应预留一个额外的元素
双引号是字符串,单引号是一个字
char c1=0; ->0x00 char c2=’\0′; ->0x00 char c3=’0’;->0x30
UTF-8:1byte,兼容ASCII码,效率高,变长(不方便内部随机访问),无字节序问题
UTF-16:BE/LE 2bytes 定长(不方便内部随机访问),有字节序问题
UTF-32:BE/LE 4bytes 定长(不方便内部随机访问),有字节序问题
windows的文件可能有BOM,在其它平台使用可去掉

指针表示方法T,存贮地址,间接访问值的操作t,指针自身也有地址t,&t
char ch=’a’; char* cp=&ch;
表达式 左值 右值
&ch 非法 ch的地址
*cp ch的地址 ch的值=a
*cp+1 非法 ch的值+1=b
*(cp+1) ch的地址+1 ch的地址+1的值 注意内存溢出

char s[] = ‘hello’; //数组s不可变,s[index]的值可以变
char* P1 = s;
char* p= “hello”; //指针p可变,p[index]的值是否可变取决于指区间的存储区域是否可变
float* P=&F;
指针指向的内容P = 内容F <- 内容地址&F
int
a[4];批针的数组,数组中的每个内容是指针
int(b)[4]; 数组的指针,指针指向的是一个数组
指向指针的指针 int** c=&P1;
指针确保初始化并赋值,小心意外发生
int
a = NULL;不指向任何东西时的状态,指针不用时置NULL,使用前先判断是否为NULL,nullptr(新)
定义函数指针: typedef void(*FuncPtr)(); FuncPtr funcPtr;

const 常量,修饰不充许修改,先看左侧最近的部分,没有则看右侧
char const* s; const char *; 内容不可变
char* const s; 指针不可变
char const* const s; 指什及内容都不可变

全局初始化区GVAR
全局末初始化区bss
代码区text
堆 heap-队列 先进先出 ,整个程序范围内new,malloc建立,注意delete,free释放,
栈 stack 先进后出,函数体内,语句块{},windows默认大小1M,linux8/10M,ulimit -s查看

内存分配 地址低–>高
代码–>数据(GVAR–>常量–>BSS–> 堆cd )–> 空闲内存 <–栈cc <–系统保留

资源管理方案RAII,依托栈和析构函数管理所有资源,智能指针代表std:auto_ptr(C++11废弃,17删除),销毁时管理的对象也自动deldete,会发生所有权转移
unique_ptr(局限较大),专属所有权,不支持复制和赋值,可以使用std::move()进行控制权的转移
auto w=std:make_unique< int >(10); *(w.get());
auto i = unique_ptr< int>(new int(10));
boost:shared_ptr,引用计数共享一个对象,引用计数为0时没有被使用,可以进行析构销毁,防止循环引用
weak_ptr,观察者模式与shared_ptr共同工作,只对shared_ptr进行引用,不计数,shared_ptr销毁时也一同销毁.

引用是一种特殊的指针,不充许修改的指针,int x=1;int& rx=x;相当于小名,别名

string.h 字符串常用的操作,尽量使用安全的API
底层操作有风险时在预处理器定义#define _CRT_SECURE_NO_WARNINGS,关闭安全警告C4996
strlen(s) 返回字符串的长度,不包含’\0′
strlen_s()
strcmp(s1,s2) 相同返回0,s1<s2返回小于0,否则大于0,自左向右以ASCII值比较
strcpy(s1,s2) 字符串s2拷贝复制到s1,注意s1空间长度
strcpy_s(s1,STR_LEN_NUM,s2)
strnpy(s1,s2,n)字符串s2前n个字符拷贝复制到s1,注意s1空间长度
strnpy_s(s1,STR_LEN_NUM,s2,n)
strcat(s1,s2) 字符串s2拼接到s1,注意s1空间长度
strcat_s(s1,STR_LEN_NUM,s2)
strchr(s1,ch) 查找s1中字符ch的第一次出现位置
strstr(s1,s2) 查找s1中字符串s2的第一次出现位置

string(新)namespace std 对性能要求不是特别高的可以使用
string s; string s=”hello”; string s (“hello”); string s= string(“hello”);
s.length() s.size() s.capacity() == != > >= < <=(比较原则同老版)
转为C风格的字符串const char* c_str = s.c_str();
随机访问某个字符 s[0] == “h”;
字符拷贝 string s2 = s;
连接 +, += string s3 = s+s2; s += s2;

if(p !=NULL){
….
}else if(…){
….
}else{
….
}

switch(){
case: xxx:
{…
break;}
default:
break;
}
while(..){…}
do{…}while(..);
for (…;..;..){…}

重载时函数另一种指针方式调用,每个函数都有一个入口地址
int(p)(int); 定义指针函数,与test函数相对应,数据类型(指针变量名)(参数表)
p=test; 指向test函数
int result = p(1); 调用test函数
注意:int
p(int); //是函数,返回的是一个指针

命名空间
namespace coust{
int test(int);
}
using namespace coust
coust::test(1)

VC++ 调作约定设置影响传参(默认/Gd)
优化-内联函数的扩展->/Ob1
inline int Xxxx(){} 内联过于复杂可能失效

传统的 printf,scanf,getch,gets..坑多可移植性差,不可编程
C++I/O流,可编程,简化编程iostream.h,fstream.h
ios<--istream<--cin
                    <--ifstream
                    |<--iostream <--fstream
    <--ostream<--ofstream
                    <--cout,cerr,clog

streambuf<--strstreambuf
                <--filebuf

IO标准缓存模式:按块(文件),按行(\n),不缓存
#include <iostream> //流
#include <string.h> //使用字符串
#include <string> //使用新字符串
#include <assert> //断言
#include<vector> //动态数组
#include<list> //列表
#include<queue> //队列
#include<stack> //栈
#include<map> //map
#include<algorithm> //算法
#include<memory> //内存
#include <math.h> //数学
vector<int> vec={1,2};
vec.push_back(3);vec.capacity/size(容量/已存贮的个数)
vec.insert(--vec.end(),4);
vec.pop_back();vec.erase(vec.end()-1);

避免同一个文件被include多次
#ifndef _SOMEFILE_H
#define _SOMEFILE_H
…通过宏来防止,可移植性好,无法防止宏名重复,不易排错
#endif //_SOMEFILE_H

#pragma once 通过编译器来防止,易排错,可移植性不好

浅拷贝:只拷贝指针地址,易引发多次释放
深拷贝:拷贝指针指向重新分配堆内存,浪费空间,但不会导致多次释放
写时复制优化策略
引用计数
C++新标准的移动语义

void* NULL nullptr

//C定义
#define NULL ((void *) 0)
//C++定义
#ifndef NULL
    #ifdef _cplusplus
        #define NULL 0
    #else
        #define NULL ((void *)0)
    #endif
#endif
//C++11定义
nullptr->(void *)0 ,NULL ->0;

类型转换
隐式转换: double f = 1.0/2;
显式转换: (类型说明符)(表达式)
C类型转换时任意类型之间都可以转换,编译器无法判断其正确性,难于错误定位
C++:const_cast用于转换指针或引用,去掉类型的const属性
reinterpret_cast重新解释类型,很危险操作,不检查指向内容,也不检查指针类型本身,但要转换前后的类型所占用内存大小一致,否则引发编译错误
static_cast用于基本转换,有继承关系对象和类指针之间的转换,由程序员确保转换是安全的
dynamic_cast 只能用于含有虚函数的类,必须用在多态体系中,向下转换时如有非法情况对于指针返回NULL


编程思想

设计模式:面向对象可复用的常见23种,反模式,企业应用构架模式…
创建型:结构型:行为型
单列模式-思路有一个私有构造函数,无法通过new直接实例化,包含一个静态私有成员变量instance和静态公有方法instance(),将构造与析构私有化
观察者模式-订阅,解耦
适配器模式(Adapter)-1使用多重继承,接口继承方式.2组合的方式

泛型编程思想
更加直接抽象,静态期多态,将算法 与特定类型,结构剥离,尽可能代码复用 template


STL
空间配制器allocator
容器 序列式string vector list deque 关联式map set multimap multiset
适配器stack queue priority_queue
仿函数greater less …
算法find swap reverse sort merge…
迭代器iterator const_iterator reverse_iterator const_reverse_iterator

for_each()
map<string,double> sts;
sts[“lim”]=99.9; //可修改值
sts.insert(pair<string,double>(“zs”,100.0));
sts.insert(map<string,double>::value_type(“lx”,96.8));
iter =sts.begin();
注意迭代器erase时失效问题,sts.erase(iter++);iter =sts.erase(iter);iter=sts.find(“zs”);sts.erase(iter); int n= sts.erase(‘”zs”);
sts.erase(sts.begin(),sts.end());


引入C
extern “C”{
#include “libavformat/avformat.h”
}

显性包函
#pragma comment(lib,”avformat.lib”)
附加目录
属性-常规:输入-附加依赖项


UI

  1. Duilib
  2. clayui
  3. libuiDK windows
  4. QT IDE->Qt Creator
    https://www.qt.io/
  5. wxWidgets库

网络
1. Linux下的Muduo

  1. BOOST的ASIO库和非boost库版的asio
    http://think-async.com/
    是一个异步IO库,封装了对Socket的常用操作,简化了基于socket程序的开发。支持跨平台。 注:要配置Boost库,还要熟悉Boost,还是麻烦;

  2. libev
    是一个C语言写的,只支持linux系统的库

  3. libuv
    linux下用libev实现,Windows下用IOCP实现;
  4. Libevent
    是一个C语言写的网络库, 官方主要支持的是类linux 操作系统, 最新的版本添加了对windows的IOCP的支持。由于IOCP是异步IO,与linux下的POLL模型,EPOLL模型,还有freebsd的KQUEUE等这些同步模型在用法上完全不一致,所以使用方法也不一样,就好比ACE中的Reactor和Proactor模式一样, 使用起来需要转变思路。如果对性能没有特别的要求, 那么使用libevent中的select模型来实现跨平台的操作, select模型可以横跨windows, linux, unix,solaris等系统。
  5. ACE库
    http://www.cs.wustl.edu/~schmidt/ACE.html
    是一个大型的中间件产品,代码20万行左右,过于宏大,一堆的设计模式,架构了一层又一层,使用的时候, 要根据情况,看你从那一层来进行使用。支持跨平台。注:除非特别需要,否则不建议;
  6. Qt有nerwork

  7. POCO
    POCO C++ Libraries 提供一套 C++ 的类库用以开发基于网络的可移植的应用程序,功能涉及线程、线程同步、文件系统访问、流操作、共享库和类加载、套接字以及网络协议包括:HTTP、 FTP、SMTP 等;其本身还包含一个 HTTP 服务器,提供 XML 的解析和 SQL 数据库的访问接口。POCO库的模块化、高效的设计及实现使得POCO特别适合嵌入式开发。在嵌入式开发领域,由于C++既适合底层(设备I/O、中断处理等)和高层面向对象开发,越来越流行。
    http://pocoproject.org/

  8. libcurl
    libcurl是免费的轻量级的客户端网络库,支持DICT, FILE, FTP, FTPS, Gopher, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMTP, SMTPS, Telnet, TFTP. 支持SSL, HTTP POST, HTTP PUT, FTP上传, HTTP form上传,代理,cookies, 用户名与密码认证。
    如果你开发的是客户端,libcurl是一个不错的选择。
    http://curl.haxx.se/libcurl/

  9. c++ sockets library
    封装了sockets C API的C++类库。支持SSL, IPv6, tcp 和 udp sockets, sctp sockets, http协议, 高度可定制的错误处理。
    http://www.alhem.net/Sockets/

  10. C++ Socket Class for Windows ,http://www.adp-gmbh.ch/win/misc/sockets.html;
    注:这个文章的文件不可以下载自己复制 保存 h 和 cpp文件;
    觉得很不错,也很简单,例子很明了; 不过有一个小小的缺点,只收发字符串,而且接收函数中的判断也有点不好;如果要用这个库传输文件等数据,需要 自己重载 收发函数,不过也很简单;

  11. SimpleSockets,
    http://sockets.carrierlabs.com/index.html
    跨平台,支持 TCP ,UDP;注:这个编译简单而且用起来也简单

You must be logged in to post a comment