当前位置: 首页 > news >正文

受欢迎的丹阳网站建设朝阳网站建设 高碑店

受欢迎的丹阳网站建设,朝阳网站建设 高碑店,厦门设计公司有哪些,软件开发平台都有哪些真正的成熟应该并不是追求完美#xff0c;而是直面自己的缺憾#xff0c;这才是生活的本质。 文章目录一、初见list1.list的迭代器失效和基本使用2.list的operations操作接口#xff08;看起来挺不错的接口#xff0c;但可惜不怎么实用#xff09;3.vector和list的排序性能…真正的成熟应该并不是追求完美而是直面自己的缺憾这才是生活的本质。 文章目录一、初见list1.list的迭代器失效和基本使用2.list的operations操作接口看起来挺不错的接口但可惜不怎么实用3.vector和list的排序性能对比list的sort接口不常用的原因list的排序效率不高二、list迭代器的基本框架结构体指针无法满足需求类封装运算符重载让迭代器的行为像指针一样三、vs和g下string结构的说明1.vs下的string结构2.g下的string结构一、初见list 1.list的迭代器失效和基本使用 1. list的底层是由带头双向循环链表实现的与vector和string不同的是list的遍历要通过迭代器来实现就算我们不知道list迭代器的底层实现机制但并不影响我们使用迭代器这就是迭代器对于所有容器带来的好处无论你是什么容器都有统一的遍历方式那就是迭代器。 2. 范围for的实现本质就是通过迭代器范围for可以遍历容器的迭代器对迭代器进行解引用然后依次拷贝给元素e所以C11的范围for没有什么新花样本质上使用的还是迭代器实现的。在编译器编译代码的时候会傻瓜式的将范围for替换为迭代器的代码然后进行编译运行。 3. 数据结构初阶阶段所使用的尾插尾删头插头删对于list依旧可以正常使用。 void test_list1() {listint lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);listint::iterator it lt.begin();//迭代器属于类的内嵌类型while (it ! lt.end()){cout *it ;it;}cout endl;lt.push_front(10);lt.push_front(20); lt.push_front(30);lt.push_front(40);for (int e : lt){cout e ;}cout endl;lt.pop_back();lt.pop_back();lt.pop_front();lt.pop_front();for (int e : lt){cout e ;}cout endl; }4. 对于list来说和vector一样我们可以用迭代器区间配合find进行元素对应的某一个节点的查找并返回该节点对应的迭代器位置。 5. 在list这个容器中只要对某一个节点进行操作就离不开迭代器迭代器就是list的唯一因为像链表这样的数据结构他是无法支持随机访问的所以通过下标随机访问的方式是不可行的那么我们就只能通过STL提供的迭代器来对某一节点进行操作。 6. 对于list来说insert不会导致迭代器失效vector存在迭代器失效是因为在扩容时reserve采取异地扩容的方式这就导致原有迭代器指向了已经被释放的空间。 但list并不存在扩容这样的操作list直接按需申请空间你要插入多少个节点那我就申请多少个节点然后将所有的节点链接到头结点后面就好了所以insert之后迭代器依旧可以继续使用因为他对应的节点空间不会被销毁依旧好好的存在着。 7. 而对于erase来说就不一样了erase会释放迭代器对应节点的空间自然erase之后迭代器就会失效如果想要继续使用迭代器则可以利用erase的返回值erase会返回被删除节点的下一个节点的迭代器我们可以用erase的返回值来更新迭代器。 void test_list2() {listint lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);listint::iterator pos find(lt.begin(), lt.end(), 3);if (pos ! lt.end()){lt.insert(pos, 30);//insert之后pos迭代器肯定不会失效。}cout *pos endl;(*pos);for (int e : lt){cout e ;}cout endl;lt.erase(pos);//erase之后迭代器会失效因为节点空间被释放了cout *pos endl;for (int e : lt){cout e ;}cout endl; }2.list的operations操作接口看起来挺不错的接口但可惜不怎么实用 1. resize用于调整链表的空间如果是调整大一些那就是一个一个的申请节点尾插到链表上面去。 如果是调整小一些那也需要一个个的释放节点相当于尾删节点。 但这个接口list不喜欢用。 2. clear用于释放除头结点之外的所有节点调用clear之后链表的size大小也就变为了0但需要和析构函数区分开来析构函数会将头结点的空间也给释放掉而clear仅仅只是将存储有效数据的所有节点释放掉。后面list模拟实现之后就会有一个更深层次的理解。 3. 下面的operations的操作接口用的非常少就是看起来确实挺有用的感觉挺不错但在实际应用的时候就不怎么常用了这也就是库的设计者在想的时候想的很好但是在程序员实际使用的时候并没有那么的实用。 这就是在做计划的时候设计的很好但等到实际使用的时候发现没啥用价值不大。 4. remove相当于finderase可用于链表中某个具体节点的删除如果删除的数据不存在则什么也不会发生并不会报错。 5. 链表单独提供了一个排序接口sort而没有用算法库里面的sort这其实就涉及到迭代器的类型问题。 迭代器从功能上来说可以分为三类只能的单向迭代器单链表、哈希表既能也能 - - 的双向迭代器list带头双向循环链表既能也能 - - 还能±某个具体的数的随机迭代器string、vector。 6. 算法库的sort底层用的是快速排序为了key值选的合适快排会进行三数取中所以会进行迭代器的作差而list的双向迭代器肯定不支持做差所以调用算法库的sort就会报错。 如果想要排序链表那就只能调用list类的成员函数sort来进行排序list的sort底层用的是归并排序。 7. unique可以对链表进行去重但去重必须建立在排序的基础之上如果不排序就去重则去重的结果会发生问题。 挨着的相同数字会被去重如果不挨着unique调用后的结果就会出错这一点有点像去除数组中重复元素那个题快慢指针法进行去重那个我记得也是建立在有序的情况下进行重复元素的删除的这里的unique的道理和快慢指针相同。 8. merge可以合并两个链表reverse用于逆置链表splice可以转移一个链表的节点或某一区间的节点或所有节点到另一个链表上面去。 //operations操作接口有用但用处不大和我们做的时间规划表一样想的挺好但在实际用的时候并没有那么常用。 void test_list3() {listint lt;lt.push_back(1);lt.push_back(9);lt.push_back(5);lt.push_back(2);lt.push_back(5);lt.push_back(2);for (int e : lt){cout e ;}cout endl;lt.remove(3);//removefinderaselt.remove(30);//如果删除的元素不存在则什么也不会发生for (int e : lt){cout e ;}cout endl;lt.sort();//链表单独提供一个排序没有用算法库里面的//sort(lt.begin(), lt.end());//这样进行链表排序是不行的//迭代器功能分类//1.单向迭代器 单链表//2.双向迭代器 -- list//3.随机迭代器 -- - vectorstringfor (int e : lt){cout e ;}cout endl;//必须先排序再去重lt.unique();//去重算法是建立在有序的基础上。去重有点像快慢指针删除数组重复元素所以如果重复数字不挨着unique就会出现错误。for (int e : lt){cout e ;}cout endl;lt.reverse();逆置lt.merge();归并lt.splice();拼接转移 }3.vector和list的排序性能对比list的sort接口不常用的原因list的排序效率不高 1. 测试排序性能建议在release版本下面进行测试debug版本下会由于编译器版本的差异产生不同的现象对于性能的测试release版本下面更加准确debug底层会由于某些优化等等导致产生的结果不够精确。 2. 在数据量大概是十万左右的情况下vector的排序性能大概是list排序性能的二倍左右所以说list的排序性能很低了相对于vector。 3. 有人做过比喻如果你要排序list倒不如先将list的数据拷贝到vector进行排序等排完序再将数据拷贝回list里面去就算这样的排序的性能都是要比直接用list进行排序的性能要高不少。从结果可以看到vector的排序性能明显要高于list。 当然如果数据量很小的话vector和list的差别就没有那么大了那时候的排序时间就相差无几了。 4. 所以如果在数据量很大的情况下排序不会选择list的sort其实主要是list的空间不连续在访问不连续的空间时消耗时间还是蛮大的。而连续的vector空间在访问时消耗就比较小CPU高速缓存的命中率也高这也正是vector数据结构独有的优势。 5. 如果不头插头删vector就比较好如果频繁头插或中间插入删除等list的结构优势就体现出来了因为vector是连续的空间list是一个一个的节点一个需要挪动数据一个不需要挪动数据。 //1.vector排序和链表排序的性能对比所以如果你要排序就不要将数据放到链表里面去这也正是链表的sort接口不常用的原因。 //2.N个数据需要排序vector 算法sort list sort void test_op()//优化这部分直接看release版本即可debug版本对于不同的结构在底层优化达到的效果都不太一样。主要看release即可。 {srand(time(NULL));const int N 100000;vectorint v;v.reserve(N);listint lt1;listint lt2;for (int i 0; i N; i){auto e rand();v.push_back(e);lt1.push_back(e);//lt2.push_back(e);}// 拷贝到vector排序排完以后再拷贝回来int begin1 clock();//for (auto e : lt1)//{// v.push_back(e);//}sort(v.begin(), v.end());//调用算法库的sort对vector进行排序//size_t i 0;//for (auto e : lt1)//{// e v[i];//}int end1 clock();int begin2 clock();lt1.sort();int end2 clock();printf(vector sort:%d\n, end1 - begin1);printf(list sort:%d\n, end2 - begin2); }二、list迭代器的基本框架结构体指针无法满足需求类封装运算符重载让迭代器的行为像指针一样 1. C为了能够支持泛型编程搞出来内置类型的构造实则编译器会在这里进行特殊处理区分开泛型和内置类型使用时可以用类型的构造函数来进行初始化内置类型一般初始化为0等值自定义类型会调用该类的默认构造。 2. 迭代器是类的内嵌类型行为像指针一样可以解引用和或 - - 。 vector和string的迭代器都是由原生指针实现的那是因为他们的底层是一个动态的顺序表内存是连续的解引用迭代器就是解引用原生指针那自然就可以拿到对应数组位置的内容而list的迭代器对应的是一个结构体是一个自定义类型并非原生指针的内置类型所以解引用迭代器我们拿到的是结构体对象而并非是数据内容这就不符合迭代器的特征因为迭代器的本意就是要解引用拿到数据而我们拿到的是一个结构体对象这就有问题了。 所以这个时候我们就需要类封装和运算符重载来实现list的迭代器了以便于他的迭代器能够解引用和或 - - 只要用运算符重载当然就离不开类解引用迭代器能够获得对应结构体数据则迭代器就不简单是一个原生指针了他应该是一个对象这个对象的类成员函数可以实现解引用 - - 等功能。 3. 这就好比年月日不支持 - - 等操作那我们就封装一个日期类在日期类里面实现日期的 - - 等操作。这里的迭代器也是这个意思你普通的结构体指针node *不是不支持解引用拿到数据 - - 等操作吗那我就封装一个类在这个类里面利用运算符重载让你的结构体指针node *支持迭代器操作这不就好了吗 4. 用一个结点的指针就可以作为list迭代器的成员变量了迭代器本质就是一个对象这个对象的成员变量是结构体指针通过迭代器类和迭代器对象我们才能让list的迭代器实现解引用加加减减等操作。 5. 为了支持泛型可以看到STL库在参数设计上采用模板的形式在实现部分将内置类型也看作了自定义类型C让内置类型也支持构造赋值拷贝构造等成员函数就是为了在泛型编程下无论是自定义类型还是内置类型都能够统一用模板参数来处理等到具体使用的时候在根据模板参数类型的不同实例化出不同的模板这样在编程时可大大提升代码的可维护性泛型编程可以省去很多不必要的代码。 namespace wyn {templateclass Tstruct list_node{list_node* _next;//指向下一个结点的结构体指针list_node* _prev;//指向前一个结点的结构体指针T _data;//数据类型是泛型可能是内置类型也有可能是自定义类型list_node(const T x)//new结点的时候会调用构造函数但编译器默认生成的无参构造函数无法满足我们的要求//所以我们需要自己写一个带参数的构造函数因为new结点时需要将数据作为参数传递无参不符合要求。:_next(nullptr),_prev(nullptr),_data(x){}};templateclass Tstruct __list_iterator{typedef list_nodeT node;node* _pnode;//迭代器类的成员就是一个结构体指针_pnode__list_iterator(node* p):_pnode(p){}T operator*()//返回_data的引用则解引用迭代器可以修改结点对应的数据{return _pnode-_data;}__list_iteratorT operator(){_pnode _pnode-_next;return *this;}bool operator!(const __list_iteratorT it)//比较两个迭代器是否相等就是比较结点指针相不相等{return _pnode ! it._pnode;}};templateclass Tclass list{typedef list_nodeT node;//将实例化后的类模板list_nodeT类型重定义为nodepublic:typedef __list_iteratorT iterator;//将实例化后的类模板__list_iteratorT类型重定义为iteratoriterator begin(){//iterator it(_head-_next);//return it;//上下这两种写法是等价的。return iterator(_head-_next);//返回迭代器类的匿名对象参数传结构体指针迭代器类的成员变量只有一个结构体指针。//匿名对象可以省下我们自己定义出对象然后再返回这样比较麻烦。}iterator end()//迭代器对象出了作用域被析构掉所以用传值返回不能用传引用返回{return iterator(_head);//end()返回的是最后一个元素的下一个位置的迭代器所以我们返回的是哨兵卫结点的迭代器对象。}void empty_initialize() {_head new node(T());//node实现的构造函数是带参数的调用T类型的默认构造初始化//new一个结点new会自动调用node类的带参构造函数我们给构造函数传一个泛型的匿名对象//保证结点存储的数据类型是泛型既有可能是内置类型也有可能是自定义类型所以传匿名对象。//如果是自定义类型会调用其类的无参构造函数如果是内置类型基本是0或NULL等初始值//我们可以认为内置类型也有构造函数这样的写法实际是为了支持C的泛型编程所搞出来的//如果是内置类型编译器会做特殊处理。_head-_next _head;_head-_prev _head;}list(){empty_initialize();}void push_back(const T x){node* newnode new node(x);//这里所传x的类型是不确定的他的类型取决于调用方给模板参数所传的值。//如果T是自定义类型那x就是对象如果T是内置类型x就是变量。node* tail _head-_prev;tail-_next newnode;newnode-_prev tail;newnode-_next _head;_head-_prev newnode;//insert(end(), x);}private:node* _head;}; }void test_list1(){listint lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);//内嵌类型 -- 迭代器需要能够1.解引用能够取到结点的数据 2.并且可以或--进行移动//string和vector的iterator原生指针能够使用是因为数组结构正好支持迭代器行为。//list如果用原生指针它的数组结构无法支持迭代器行为因为list的空间是不连续的。//为了支持list的迭代器我们用类的封装和运算符重载进行支持。listint::iterator it lt.begin();//由于迭代器对象的拷贝构造没有实现所以用编译器默认生成的浅拷贝。while (it ! lt.end())//vector和string可以用来进行判断但list这里只能用!这里会调用it对应类的运算符重载{//it.operator*(){} --- 转换为调用自定义类型对应类内的运算符重载函数//it.operator(){}cout *it ;//*it是自定义类型iterator的运算符重载iterator是进行封装的类型it;//it也是自定义类型iterator的运算符重载。//(*it); --- it.operator*()函数的引用返回值进行自增返回值可能是自定义类型或内置类型。}cout endl;for (auto e : lt)//范围for就是傻瓜式的替换迭代器的代码begin()end()迭代器支持解引用--等操作范围for就能用{cout e ;}cout endl;}三、vs和g下string结构的说明 1.vs下的string结构 1. 下面所说的默认环境是32位平台指针为4字节。从打印结果我们可以得到两个信息一个是s1和s2的所占字节大小一样另一个是两者所占字节大小为28字节。 首先两者一样的原因是因为对象的大小和存储的数据无关因为数据是在堆区上动态开辟的分析对象大小时我们只看对象成员变量所占大小所以这就能解释为什么对象s1和对象s2的大小是一样的了。 2. 至于为什么是28字节而不是12字节这就和vs下string的结构有关系了我们实现的string有三个成员变量分别是_ptr、_size和_capacity按照内存对齐的原则应该是12字节。但我们实现的并不标准仅仅能够完成string的大部分功能而已。 vsPJ版本的STL源码中string总共占28个字节内部结构稍微复杂一点先是有一个联合体联合体用来定义string中字符串的存储空间当字符串长度小于16时使用内部固定的字符数组_buf来存放当字符长度大于等于16时从堆上开辟空间不在使用_buf数组进行存放。 3. 从调试窗口可以看到当存储数据小于16时数据内容被存放到了_Buf数组里面而_Ptr并没有指向具有有效字符的空间。当存储数据大于等于16时数据内容被存放到了_Ptr指向的动态开辟的空间里面而_Buf里面什么都没有存。 4. vs对于string的设计思想主要还是用空间换时间增大string对象的大小如果数据量比较小那就用提前开好的_Buf数组进行存储节省自己动态开辟空间的消耗。 2.g下的string结构 1. g下string是通过写时拷贝实现的string对象总共占4个字节内部只包含了一个指针该指针将来指向一块堆空间内部包含了如下字段共分为4个部分空间总大小字符串有效长度引用计数指向堆空间的指针用来存储字符串。 2.但是显示出来的string对象大小是8字节因为默认使用的环境是64位指针大小为8字节。 x86_64是64位平台指针大小为8字节 3. 在没有向对象中指针指向空间发生数据的写入的时候g下面会先发生浅拷贝先不开空间下面代码的第三张图片中我们对空间进行了写入这个时候就会发生写时拷贝重新进行空间的深拷贝。
文章转载自:
http://www.morning.ssgqc.cn.gov.cn.ssgqc.cn
http://www.morning.pmghz.cn.gov.cn.pmghz.cn
http://www.morning.pmysp.cn.gov.cn.pmysp.cn
http://www.morning.qbjgw.cn.gov.cn.qbjgw.cn
http://www.morning.skdrp.cn.gov.cn.skdrp.cn
http://www.morning.qxwrd.cn.gov.cn.qxwrd.cn
http://www.morning.lkcqz.cn.gov.cn.lkcqz.cn
http://www.morning.ccpnz.cn.gov.cn.ccpnz.cn
http://www.morning.rlns.cn.gov.cn.rlns.cn
http://www.morning.sqnxk.cn.gov.cn.sqnxk.cn
http://www.morning.lzbut.cn.gov.cn.lzbut.cn
http://www.morning.qbjrl.cn.gov.cn.qbjrl.cn
http://www.morning.pcwzb.cn.gov.cn.pcwzb.cn
http://www.morning.jlktz.cn.gov.cn.jlktz.cn
http://www.morning.wpsfc.cn.gov.cn.wpsfc.cn
http://www.morning.snzgg.cn.gov.cn.snzgg.cn
http://www.morning.tfcwj.cn.gov.cn.tfcwj.cn
http://www.morning.kqgqy.cn.gov.cn.kqgqy.cn
http://www.morning.mingjiangds.com.gov.cn.mingjiangds.com
http://www.morning.qtyfb.cn.gov.cn.qtyfb.cn
http://www.morning.cwwts.cn.gov.cn.cwwts.cn
http://www.morning.zcwtl.cn.gov.cn.zcwtl.cn
http://www.morning.wknjy.cn.gov.cn.wknjy.cn
http://www.morning.qbzfp.cn.gov.cn.qbzfp.cn
http://www.morning.zcnfm.cn.gov.cn.zcnfm.cn
http://www.morning.kjksn.cn.gov.cn.kjksn.cn
http://www.morning.fsrtm.cn.gov.cn.fsrtm.cn
http://www.morning.qxmys.cn.gov.cn.qxmys.cn
http://www.morning.nlrxh.cn.gov.cn.nlrxh.cn
http://www.morning.qbmjf.cn.gov.cn.qbmjf.cn
http://www.morning.bqwsz.cn.gov.cn.bqwsz.cn
http://www.morning.lwqst.cn.gov.cn.lwqst.cn
http://www.morning.bdkhl.cn.gov.cn.bdkhl.cn
http://www.morning.rqlbp.cn.gov.cn.rqlbp.cn
http://www.morning.rwbx.cn.gov.cn.rwbx.cn
http://www.morning.zpjhh.cn.gov.cn.zpjhh.cn
http://www.morning.qcrhb.cn.gov.cn.qcrhb.cn
http://www.morning.dmfdl.cn.gov.cn.dmfdl.cn
http://www.morning.dxqwm.cn.gov.cn.dxqwm.cn
http://www.morning.hphrz.cn.gov.cn.hphrz.cn
http://www.morning.bzlsf.cn.gov.cn.bzlsf.cn
http://www.morning.cxlys.cn.gov.cn.cxlys.cn
http://www.morning.rywn.cn.gov.cn.rywn.cn
http://www.morning.hqqpy.cn.gov.cn.hqqpy.cn
http://www.morning.jqjnx.cn.gov.cn.jqjnx.cn
http://www.morning.bpds.cn.gov.cn.bpds.cn
http://www.morning.rqmr.cn.gov.cn.rqmr.cn
http://www.morning.sryhp.cn.gov.cn.sryhp.cn
http://www.morning.crfyr.cn.gov.cn.crfyr.cn
http://www.morning.ybnps.cn.gov.cn.ybnps.cn
http://www.morning.kxwsn.cn.gov.cn.kxwsn.cn
http://www.morning.bntfy.cn.gov.cn.bntfy.cn
http://www.morning.hrhwn.cn.gov.cn.hrhwn.cn
http://www.morning.xsbhg.cn.gov.cn.xsbhg.cn
http://www.morning.jqsyp.cn.gov.cn.jqsyp.cn
http://www.morning.gmwqd.cn.gov.cn.gmwqd.cn
http://www.morning.jlktz.cn.gov.cn.jlktz.cn
http://www.morning.qzdxy.cn.gov.cn.qzdxy.cn
http://www.morning.qstjr.cn.gov.cn.qstjr.cn
http://www.morning.lblsx.cn.gov.cn.lblsx.cn
http://www.morning.dyght.cn.gov.cn.dyght.cn
http://www.morning.gblrn.cn.gov.cn.gblrn.cn
http://www.morning.tllws.cn.gov.cn.tllws.cn
http://www.morning.lsmgl.cn.gov.cn.lsmgl.cn
http://www.morning.knqck.cn.gov.cn.knqck.cn
http://www.morning.sltfk.cn.gov.cn.sltfk.cn
http://www.morning.qftzk.cn.gov.cn.qftzk.cn
http://www.morning.qywfw.cn.gov.cn.qywfw.cn
http://www.morning.wwjft.cn.gov.cn.wwjft.cn
http://www.morning.pypqf.cn.gov.cn.pypqf.cn
http://www.morning.tznlz.cn.gov.cn.tznlz.cn
http://www.morning.thrgp.cn.gov.cn.thrgp.cn
http://www.morning.rqknq.cn.gov.cn.rqknq.cn
http://www.morning.lnfkd.cn.gov.cn.lnfkd.cn
http://www.morning.lxfqc.cn.gov.cn.lxfqc.cn
http://www.morning.qljxm.cn.gov.cn.qljxm.cn
http://www.morning.sjmxh.cn.gov.cn.sjmxh.cn
http://www.morning.fplqh.cn.gov.cn.fplqh.cn
http://www.morning.gwwtm.cn.gov.cn.gwwtm.cn
http://www.morning.fpzpb.cn.gov.cn.fpzpb.cn
http://www.tj-hxxt.cn/news/271141.html

相关文章:

  • 上海婚恋网站排名苍南最好的网站建设公司
  • wordpress icp涵数seo怎么优化软件
  • 宁波江北建设局网站wordpress 如何登录地址
  • 中国信誉建设网站广州网站开发十度网络最好
  • 燕莎网站建设个人如何做百度推广
  • 儿童网站建设个人博客大全
  • html5新手做的网页seo推广编辑招聘
  • 张掖网站建设清空回收站 wordpress
  • 怎样为企业设计网站网站建设 个人
  • 重庆响应式网站多少钱网站建设与设计毕业shej
  • 哪些网站可以做招商广告湖南省建筑信息网
  • 现在网站主怎么做淘宝客石岩做网站哪家好
  • 网站开发设nas wordpress外网
  • 做现货黄金网站毕业设计旅游网站开发
  • 微网站内容淘宝关键词挖掘工具
  • 拨付网站建设费用的报告教学网站开发背景
  • 高端网站建设设计公司哪家好网站字体规范
  • 西安哪个公司做网站广告投放就选亿企联盟
  • 社交网站开发网站收录突然减少
  • 大良营销网站建设市场拥有服务器后如何做网站
  • 定制网站建设济南网站建设 域名 数据库
  • 企业网站建设要点北京网站建设公司收购
  • 网站式登录页面模板成都做微信小程序的公司
  • 如何套用别人网站做页面wordpress自定义404
  • 手机app 网站学校如何重视校园网站建设
  • 阳江网站建设推广公司电话自己做网站推广费用大
  • 国内哪个网站用wordpress个人网站经营 合法么
  • 保定 营销型网站建设门户网站申请
  • 昆山网站建设推广1m带宽可以建设电商网站吗
  • 图片素材网站有哪些网站建设定价