成都网站建设设计

将想法与焦点和您一起共享

2022-12-15c++总结-创新互联

文章目录
  • c++学习之路(总结篇)持续更新
    • 基本概念理解
      • 关于.h .hpp .cpp的理解
      • namespace和#ifdef的理解
      • 封装成dll和lib区别
      • stdafx.h和stdafx.cpp
      • 全局变量global和静态变量static区别
      • main函数的参数argc,argv
    • 类型含义理解
      • 符号变量const和define
      • 枚举类型enum
      • 结构体struct
      • 联合体union
      • 类class
      • 指针p
    • 编译器常用操作
      • Visual Studio(VS)---Windows
    • 中级知识
      • 回调函数
      • 结构体作为形参传递
      • 返回数组的方法
      • 内存分配
    • 类的用法
      • 继承和派生
      • 构造函数
        • 关于派生类的构造函数
      • 拷贝(复制)构造函数
      • 析构函数
        • 关于派生类的析构函数
      • 对象
      • 成员变量
      • 引用
      • 友元函数friend
      • 内联函数inline
      • this指针
      • 静态成员
      • 静态成员函数
        • 类的静态成员函数访问非静态成员变量方法
      • 重载运算符和重载函数
      • 虚函数virtual
      • 多态
      • 赋值
      • const关键字
      • 模板
        • 函数模板
        • 类模板
    • 常用的头文件

龙华网站制作公司哪家好,找创新互联建站!从网页设计、网站建设、微信开发、APP开发、成都响应式网站建设公司等网站项目制作,到程序开发,运营维护。创新互联建站于2013年开始到现在10年的时间,我们拥有了丰富的建站经验和运维经验,来保证我们的工作的顺利进行。专注于网站建设就选创新互联建站
c++学习之路(总结篇)持续更新

根据之前学习的进行总结,温故而知新,理解有误请大佬们评论区指正,感谢~

基本概念理解

在整个代码编译过程中,除了语言上的标准外,对编译的概念理解通透也是必需的:

关于.h .hpp .cpp的理解
  1. 以我现在的理解,.h和.cpp其实就类似于一本书的目录和内容,那么也就是说这就是一本书(C++中称为package),所以他俩的名字是一样的,那么分工具体是怎样的,就是.h是概括,目的是为了方便我们快速查找想要的内容,所以在.h文件中主要是方法和变量的声明;.cpp是具体的内容,所以是具体方法的定义和实现;其实两个的存在并不是必要的(C语言就没有也可以实现功能),但是有了这两个可以一方面很方便编写很多代码时的快速查找,另一方面便于封装,直接#include<.h>就可以;
  2. .hpp其实是将.h和.cpp混合在一起作为.h被调用,一般适用于公共的开源库;
  3. #include<.h>和#include ".h "两者的区别?
    <>使用时预处理程序会在系统默认路径或括号内的路径进行查找,通常适用于系统公共的头文件;“”使用时是在程序源文件所在目录的路径进行查找,找不到才会在系统默认路径进行查找,通常适用于自己写的头文件。
namespace和#ifdef的理解
  1. 什么情况下需要加using namespace?
    现在常见的 就是 using namespace std; cv; openni… namespace就是命名空间的意思,那么std就是包含了c++中常用的标识符的一个空间,如果在程序中要使用一个标识符例如cout,那么cout这个东西是在std中定义的,所以理论上应该是std::cout,但实际上为了书写代码时的简洁性,通常在开头就会写上std,程序中直接写cout时,它就会寻找是不是在std中定义过,但是这样会造成一个问题,如果你自己定的命名空间中包含std的内容的话,std中的命名空间就会很容易被污染掉,那会出现很多问题;其次,命名空间的实质是为了避免全局变量命名的冲突,也就是说它是把这个程序给封起来了,如果两个cpp中使用相同的函数名,通过命名空间可以将其区分;
    所以程序中还是尽可能减少使用using namespace, 在程序代码中养成加命名空间的习惯;
  2. 程序中开头#ifdef #else #endif的作用是?与#ifndef的区别?
    首先在c++中以#开头的指令都被称之为预处理指令,程序编译分为三部分:预处理、编译和汇编,与if有关的称之为条件编译指令,只有为真时,才会进行这部分代码的编译;#ifndef是指不为真时(if not),进行编译;加上def代表的是define,是指定义,代表如果if后面的东西define过了,后面的程序才会被编译。
    常常用在.h开头,例如一个test.h:
#ifndef TEST_H_
#define TEST_H_
///代码
#endif
封装成dll和lib区别

首先,dll和lib都是链接库,dll是动态链接库,lib是静态链接库。静态库是指在链接的过程中,将该库中的代码完全复制到可执行文件中;动态库是指可以被不同进程调用但不属于可执行文件的函数,可由多个程序同时使用。总之,lib是编译时用到的,dll是运行时用到的。

stdafx.h和stdafx.cpp

StdAfx.h, StdAfx.cpp这些文件用于生成名为.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。

全局变量global和静态变量static区别

全局变量和静态变量在内存中存放在同一位置,即静态区/全局区。
从作用域来看:
静态变量的生命周期为整个源程序,其作用域仍与普通变量相同
静态全局变量也具有全局作用域,他与全局变量的区别在于如果程序包含多个文件的话,他作用于定义它的文件里,不能作用到其他文件里,即被static关键字修饰过的变量具有文件作用域。这样即使两个不同的源文件都定义了相同的静态全局变量,他们也是不同的变量
从生命周期看:
都在程序运行时期全程有效
全局变量:用extern声明,也称之为外部变量,是在方法外部定义的变量。它不属于哪个方法,而是属于整个源程序。作用域是整个源程序。如果全局变量和局部变量重名,则在局部变量作用域内,全局变量被屏蔽,不起作用。编程时候尽量不使用全局变量。
静态变量:用static声明,从面向对象的角度触发,当需要一个数据对象为整类而非某个对象服务,同时有力求不破坏类的封装性,既要求此成员隐藏在类的内部,有要求对外不可见的时候,就可以使用static。

main函数的参数argc,argv

argc 是 argument count的缩写,表示传入main函数的参数个数;
argv 是 argument vector的缩写,表示传入main函数的参数序列或指针,并且第一个参数argv[0]一定是程序的名称,并且包含了程序所在的完整路径;

类型含义理解 符号变量const和define

通常我们知道有变量和常量的定义,例如int a=10; 那么a是个变量,值可以变的量;10是个常量,值不能变的量;那么在c++中例如用const int a=10,理论上a是个变量,但由于const限定符,导致其是个常量,因此将其称之为符号常量;符号常量的定义通常有两种方式实现:#define和const,区别是define只是做个文本替换

枚举类型enum

enum称为枚举数据类型,就是可以一个个列举出来的东西,比如星期几或者性别,可以清楚知道里面有什么内容的数据,一般使用形式是 enum 枚举名{枚举列表, ,}枚举变量名;其中枚举名和变量名都是可有可无的,枚举列表默认是从0开始赋值,逐渐加一的一个符号常量的几何,也可以直接进行整型常量的赋值;作用就是 相比const和define有了enum可以更加简洁的定义很多个符号常量,更加方便;一般是需要定义多个符号常量时,例如errorcode或者需要定义常量时使用;

enum Type
{
    INFO,
    ERRO,
    WARN,
    DEBUG,
};
结构体struct

首次,为什么会衍生出结构体这个东西,本身我们所学的基本类型中有一维的,就是各种变量,字符串,布尔量;二维的有数组等;但是呢由于数组中的成员都是同一数据类型,那么如果不同数据类型的集合就可以用结构体来定义了。在c++中,struct定义的后面直接是变量名;而typedef struct定义的后面是结构体类型,区别就是结构体类型需要实例化之后才能访问结构体中的成员。
c++中的struct相比c中的已经扩充了很多内容,不仅可以包含不同类型的成员变量,也可以包含成员函数、可继承、可多态,那么与class的区别就是:struct中的成员默认是public的,而class中的成员默认是private

联合体union

一个 union 可以有多个数据成员,但是在任意时刻只有一个数据成员可以有值。当某个成员被赋值后其他成员变为未定义状态。

  • 默认访问控制符为 public
  • 可以含有构造函数、析构函数
  • 不能含有引用类型的成员
  • 不能继承自其他类,不能作为基类
  • 不能含有虚函数
  • 匿名 union 在定义所在作用域可直接访问 union 成员
  • 匿名 union 不能包含 protected 成员或 private 成员
  • 全局匿名联合必须是静态(static)的
类class

类其实也就是一种数据类型,跟结构体差不多,它的目的就是多了一层封装,类似于你写一堆函数放在一个cpp中,在别的里面再调用,类就相当于写了一堆函数,再封装一下,再把一堆的类放在一个cpp中,这样做的好处是在大项目中能够更加清晰看懂代码逻辑,方便组织管理代码。类是一种数据类型,它的实例化就叫做对象,不同于struct对应的变量就叫变量。
类中一般包括成员函数和成员变量,定义class 类名{public/private:成员变量;函数};类只是一个模板,不占用内存空间,只有实例化之后才会占内存,创建对象后可以通过对象名.成员名来访问类中的成员

指针p

指针这个东西其实就跟编程的底层有关了,其实在编程中定义的所有东西都会占用内存空间,那如果我们直接对内存空间进行修改的话,很大程度会增加编程的灵活性,这样指针就产生了,指针其实也就是个变量,本身也会占用内存空间,但是与一般变量不同的是,指针变量中存储的内容是内存空间的地址,通过这个地址,我们就可以找到这个内存空间对应的变量了

编译器常用操作 Visual Studio(VS)—Windows
  1. VS2019 c++封装成dll和lib的方法:
    在vs中新建生成静态库的工程,编译生成成功后,只产生一个.lib文件;在vs中新建生成动态库的工程,编译成功后,产生一个.lib文件和一个.dll文件。动态库往往提供2个文件,一个是引入库和一个DLL,引入库包含被DLL导出的函数和变量的符号名,DLL包含实际的函数和数据。在编译链接可执行文件时,只需要链接引入库,DLL中的函数代码和数据并不复制到可执行文件中,在运行的时候,再去加载DLL,访问DLL中导出的函数。
    生成DLL参考链接:VS2019 c++ dll
    生成LIB参考链接:VS2019C++ LIB
    在测试过程中,要注意的问题:
    模块计算机类型“X86”与目标计算机类型“X64”冲突:解决方案
    出现该问题的原因是:在生成lib和dll文件的时候平台没有选x64,而是默认的x86
  2. VS2019如何恢复原窗口布局?
    在选项卡窗口中----下拉选择恢复窗口布局即可
中级知识 回调函数
  1. c++中回调函数是什么?
    回调函数 我的理解是 相当于配了一个秘书,我在办公室忙着我的事情,刚开始我就通知秘书,如果外面有人来访,秘书再来告知我,无事就请勿扰。那如果没有这个秘书,那只能是我忙死了。。。
    在这个例子中,有三个人,
    我就是程序的主函数,忙着做主程序的事情
    秘书就是登记回调函数,主函数在刚开始的时候就应该通知/调用登记回调函数(有人来了再来打扰我,没人就不要打扰我)
    外人就是回调函数,当外人来了,就会触发回调函数;秘书告诉我,让我来响应回调函数。
  2. 回调函数有什么好处?
    大的好处是你的程序变成异步了。也就是你不必再调用这个函数的时候一直等待这个时间的到达、事件的发生或中断的发生(万一一直不发生,你的程序会怎么样?)。再此期间你可以做做别的事情,或者四处逛逛。当回调函数被执行时,你的程序重新得到执行的机会,此时你可以继续做必要的事情了。
  3. 回调函数怎么使用?
    主函数中要做的事情: 调用登记回调函数
    登记回调函数要做的事情:如果…触发回调函数
    回调函数:触发了之后要做什么,如何回到主函数
  4. 例子
    登记回调函数
void register(fun)
{
//新开一个线程,判断什么时候触发fun
if(...)
{
    fun();
}
}

回调函数

void callback()
{
//触发回调之后要做的事情
}

主函数

int main()
{
register(callback);
return 0;
}
结构体作为形参传递

参考链接
推荐链接中的第三种

返回数组的方法
  1. 返回一维数组(指针传递地址法)
int test*()
{
int *a[3]={0,1,2};
return a;
}
int main()
{
int *res;
res = test();
std::cout<< res[0]<< std::endl;
}
  1. 返回二维数组
    方法一:同上
    方法二:形参引用法
内存分配

在C语言中,动态分配内存用 malloc() 函数,释放内存用 free() 函数;C++中使用new 和 delete:new 用来动态分配内存,delete 用来释放内存。

int *p = new int; //分配1个int型的内存空间
delete p; //释放内存
int *p = new int[10]; //分配10个int型的内存空间
delete[] p;
通常 new 和 delete、new[] 和 delete[] 操作符应该成对出现

类的用法

参考链接:继承和派生

继承和派生

继承是指继承方式,public\protected\private;派生是指继承了基类的派生类(也就是继承了父的子),其中父的private在子和外人中均不可访问,毕竟是爸比私人的秘密哈哈哈儿子也不可以访问的哟~而父的protected可以被子访问,外人不可访问,public那就是everyone都可以访问;另外子继承了的成员变量也可以在自己的类中变更访问方式哦
class 子类名:继承方式(public/protected/private)父类名
如果派生类中的成员(包括成员变量和成员函数)和基类中的成员重名,那么就会遮蔽从基类继承过来的成员,不会构成重载。但是,基类中的成员函数仍然可以访问,不过要加上类名和域解析符。

构造函数

构造-----类的一种特殊的成员函数,它会在每次创建类的新对象时执行。构造函数可用于为某些成员变量设置初始值,名称与类名相同。
采用参数初始化表,成员变量的赋值顺序由它们在类中的声明顺序决定,初始化 const 成员变量的唯一方法就是使用参数初始化表。派生类只能采用构造函数初始化列表的方式向基类或成员对象的构造函数传递参数。

Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){
//TODO:
}

构造函数必须是 public 属性的,否则创建对象时无法调用。
不管是声明还是定义,函数名前面都不能出现返回值类型,即使是 void 也不允许;
函数体中不能有 return 语句。
构造函数是允许重载的。一个类可以有多个重载的构造函数,创建对象时根据传递的实参来判断调用哪一个构造函数。

关于派生类的构造函数

先构造基类,再构造成员,最后构造自身(调用构造函数)。
在设计派生类时,对继承过来的成员变量的初始化工作也要由派生类的构造函数完成,但是大部分基类都有 private 属性的成员变量,它们在派生类中无法访问,更不能使用派生类的构造函数来初始化。

解决这个问题的思路是:在派生类的构造函数中调用基类的构造函数。

//People(name, age)就是调用基类的构造函数

Student::Student(char *name, int age, float score): People(name, age), m_score(score){ }

定义派生类构造函数时最好指明基类构造函数;如果不指明,就调用基类的默认构造函数(不带参数的构造函数)

拷贝(复制)构造函数

参考链接
当同一个类的对象2要拷贝对象1时,例如class A:

A a1(1,2,3);
A a2(a1);

当a2实例化的时候,就会调用默认的或者非默认的(程序中重新编写的)拷贝构造函数;
只有在初始化的时候才会调用拷贝构造,而在赋值语句不会引发复制构造函数的调用。(赋值语句的等号左边是一个早已有定义的变量)

析构函数

析构-----它会在每次删除所创建的对象时执行。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。析构函数没有参数,不能被重载,因此一个类只能有一个析构函数。
在所有函数之外创建的对象是全局对象,它和全局变量类似,位于内存分区中的全局数据区,程序在结束执行时会调用这些对象的析构函数。
在函数内部创建的对象是局部对象,它和局部变量类似,位于栈区,在局部函数执行结束时会调用这些对象的析构函数。
new 创建的对象位于堆区,通过 delete 删除时才会调用析构函数;如果没有 delete,析构函数就不会被执行。

关于派生类的析构函数

创建派生类对象时,构造函数的执行顺序和继承顺序相同,即先执行基类构造函数,再执行派生类构造函数。
而销毁派生类对象时,析构函数的执行顺序和继承顺序相反,即先执行派生类析构函数,再执行基类析构函数。
为了解决多继承时的命名冲突和冗余数据问题,C++ 提出了虚继承virtual,使得在派生类中只保留一份间接基类的成员。

对象

两种创建对象的方式:一种是在栈上创建,
Student stu;
Student *pStu = &stu;
在栈上创建对象时,实参位于对象名后面,例如Student stu(“小明”, 15, 92.5f);
另外一种是在堆上创建,
Student *pStu = new Student;
delete pStu; //删除对象
栈内存是程序自动管理的,不能使用 delete 删除在栈上创建的对象;堆内存由程序员管理,对象使用完毕后可以通过 delete 删除。

成员变量

成员变量大都以m_开头,这是约定成俗的写法,不是语法规定的内容。以m_开头既可以一眼看出这是成员变量,又可以和成员函数中的形参名字区分开。
根据C++软件设计规范,实际项目开发中的成员变量以及只在类内部使用的成员函数(只被成员函数调用的成员函数)都建议声明为 private,而只将允许通过对象调用的成员函数声明为 public。
给成员变量赋值的函数通常称为 set 函数,它们的名字通常以set开头,后跟成员变量的名字;读取成员变量的值的函数通常称为 get 函数,它们的名字通常以get开头,后跟成员变量的名字。
除了 set 函数和 get 函数,在创建对象时还可以调用构造函数来初始化各个成员变量。

引用

引用的定义方式类似于指针,只是用&取代了*,语法格式为:
type &name = data;
引用必须在定义的同时初始化,并且以后也要从一而终,不能再引用其它数据,这有点类似于常量(const 变量)。
注意,引用在定义时需要添加&,在使用时不能添加&,使用时添加&表示取地址。
如果不希望通过引用来修改原始的数据,那么可以在定义时添加 const 限制,形式为:
const type &name = value;

友元函数friend

在当前类以外定义的、不属于当前类的函数也可以在类中声明,但要在前面加 friend 关键字,这样就构成了友元函数。
友元函数不同于类的成员函数,在友元函数中不能直接访问类的成员,必须要借助对象。
class Student{
public:
Student(char *name, int age, float score);
public:
friend void show(Student *pstu); //将show()声明为友元函数
private:
char *m_name;
int m_age;
float m_score;
};

//非成员函数
void show(Student *pstu){
cout}

内联函数inline

引入内联函数的目的是为了解决程序中函数调用的效率问题,这么说吧,程序在编译器编译的时候,编译器将程序中出现的内联函数的调用表达式用内联函数的函数体进行替换,而对于其他的函数,都是在运行时候才被替代。只有当函数只有 10 行甚至更少时才将其定义为内联函数.内联该函数可以令目标代码更加高效. 对于存取函数以及其它函数体比较短, 性能关键的函数, 鼓励使用内联.
在类体中定义的成员函数会自动成为内联函数

this指针

只有类的成员函数才有 this 指针,成员函数通过一个名为 this 的额外隐式参数来访问调用它的那个对象,this就是指的调用对象
this 是 const 指针,this 只能在成员函数内部使用,用在其他地方没有意义,也是非法的

静态成员

使用 static 关键字来把类成员定义为静态的,静态成员在类的所有对象中是共享的,类似于全局变量的含义
static 成员变量必须在类声明的外部初始化,具体形式为:
type class::name = value;

static 成员变量既可以通过对象来访问,也可以通过类来访问

静态成员函数

静态成员函数即使在类对象不存在的情况下也能被调用,静态函数只要使用类名加范围解析运算符 :: 就可以访问。
静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量和静态成员函数)。静态成员函数与普通成员函数的根本区别在于:普通成员函数有 this 指针,可以访问类中的任意成员;而静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量和静态成员函数)。

类的静态成员函数访问非静态成员变量方法
#includeusing namespace std;
class A
{public:
       A(int x):m_x(x){};
       static void f(A a);
    private:
       int m_x;
};
void A::f(A a)
{//静态成员函数只能引用属于该类的静态数据成员或静态成员函数。
    // cout<A a(5);
    a.f(a);
   // system("pause");
    return 0;
}
重载运算符和重载函数

重载必须满足形参的类型/个数/顺序不同,不能靠返回类型不同重载函数!
一般将功能类似的函数用于重载
重载大部分 C++ 内置的运算符,就能使用自定义类型的运算符。重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。

虚函数virtual

继承时,要养成的一个好习惯就是,基类析构函数中,加上virtual。这是为了防止内存泄漏。假设基类中采用的是非虚析构函数,当删除基类指针指向的派生类对象时就不会触发动态绑定,因而只会调用基类的析构函数,而不会调用派生类的析构函数。那么在这种情况下,派生类中申请的空间就得不到释放从而产生内存泄漏。所以,为了防止这种情况的发生,C++中基类的析构函数应采用virtual虚析构函数。

多态

多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。
C++中虚函数的唯一用处就是构成多态,基类指针可以按照基类的方式来做事,也可以按照派生类的方式来做事,它有多种形态,或者说有多种表现方式,我们将这种现象称为多态。
通过基类指针只能访问派生类的成员变量,但是不能访问派生类的成员函数。
C++提供多态的目的是:可以通过基类指针对所有派生类(包括直接派生和间接派生)的成员变量和成员函数进行“全方位”的访问,尤其是成员函数。如果没有多态,我们只能访问成员变量。
有虚函数才能构成多态,这节我们来重点说一下虚函数的注意事项:

  1. 只需要在虚函数的声明处加上 virtual 关键字,函数定义处可以加也可以不加。
  2. 为了方便,你可以只将基类中的函数声明为虚函数,这样所有派生类中具有遮蔽(覆盖)关系的同名函数都将自动成为虚函数
赋值

赋值的本质是将现有的数据写入已分配好的内存中,对象的内存只包含了成员变量,所以类对象之间的赋值是成员变量的赋值,成员函数不存在赋值问题。
把派生类对象赋值给基类对象。 把派生类对象的地址赋值给基类指针。 用派生类对象初始化基类对象的引用。 反之则不行,即不能把基类对象赋值给派生类对象;不能把基类对象的地址赋值给派生类对象的指针;也不能把基类对象作为派生对象的引用。这种转换关系是不可逆的,只能用派生类对象给基类对象赋值,而不能用基类对象给派生类对象赋值。

const关键字

const 可以用来修饰成员变量、成员函数以及对象。如果你不希望某些数据被修改,可以使用const关键字加以限定。
const 成员函数可以使用类中的所有成员变量,但是不能修改它们的值;常成员函数需要在声明和定义的时候在函数头部的结尾加上 const 关键字
class Student{
public:
Student(char *name, int age, float score);
void show();
//声明常成员函数
char *getname() const;
int getage() const;
float getscore() const;
private:
char *m_name;
int m_age;
float m_score;
};

//定义常成员函数
char * Student::getname() const{
return m_name;
}

常对象: const定义的常对象必须进行初始化,而且不能被更新。 (类名 const 对象名 ),通过常对象只能调用它的常成员函数,普通对象调用普通成员函数
常引用:被引用的对象不能被更新。 const 类型说明符 &引用名
常数组:数组元素不能被更新。 类型说明符 const 数组名[大小]
常指针:指向常量的指针。

模板 函数模板

所谓函数模板,实际上是建立一个通用函数,它所用到的数据的类型(包括返回值类型、形参类型、局部变量类型)可以不具体指定,而是用一个虚拟的类型来代替(实际上是用一个标识符来占位),等发生函数调用时再根据传入的实参来逆推出真正的类型。这个通用函数就称为函数模板(Function Template)。

templatevoid Swap(T *a, T *b){
T temp = *a;
*a = *b;
*b = temp;
}

template返回值类型 函数名(形参列表){
//在函数体中可以使用类型参数
}

类模板

//声明

template//这里不能有分号
class Point{public:
Point(T1 x, T2 y): m_x(x), m_y(y){}
public:
T1 getX() const; //获取x坐标
void setX(T1 x); //设置x坐标
T2 getY() const; //获取y坐标
void setY(T2 y); //设置y坐标
private:
T1 m_x; //x坐标
T2 m_y; //y坐标
};

//定义

templatevoid Point::setY(T2 y){m_y = y;
}

//实例化,在实例化时必须显式地指明数据类型,

Pointp1(10, 20);
Point*p1 = new Point(10.6, 109.3);
常用的头文件
  • #include 使用输入输出时
  • #include      //字符串类

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


网站题目:2022-12-15c++总结-创新互联
网站地址:http://chengdu.cdxwcx.cn/article/decpcc.html