C++新增的类功能和可变参数模板
C++新增的类功能和可变参数模板
- 新的类功能
- 默认成员函数
- 可变参数模板
- 模拟实现emplace_back
🌏个人博客主页: 个人主页
新的类功能
默认成员函数
原来C++类中,有6个默认成员函数:
- 构造函数
- 析构函数
- 拷贝构造函数
- 拷贝赋值重载
- 取地址重载
- const 取地址重载
最后重要的是前4个,后两个用处不大。默认成员函数就是我们不写编译器会生成一个默认的。C++11 新增了两个:移动构造函数和移动赋值运算符重载。
为了方便观察我们写一个简单的string
class string
{public:typedef char* iterator;iterator begin(){return _str;}iterator end(){return _str + _size;}typedef const char* const_iterator;const_iterator begin() const{return _str;}const_iterator end() const{return _str + _size;}string(const char* str = ""):_size(strlen(str)), _capacity(_size){cout << "string(char* str)" << endl;_str = new char[_capacity + 1];strcpy(_str, str);}// s1.swap(s2)void swap(string& s){::swap(_str, s._str);::swap(_size, s._size);::swap(_capacity, s._capacity);}// 拷贝构造// s2(s1)string(const string& s):_str(nullptr){cout << "string(const string& s) -- 深拷贝" << endl;reserve(s._capacity);for (auto ch : s){push_back(ch);}}// 移动构造// 临时创建的对象,不能取地址,用完就要消亡// 深拷贝的类,移动构造才有意义string(string&& s):_str(nullptr){cout << "string(string&& s) -- 移动拷贝" << endl;swap(s);}// 赋值重载string& operator=(const string& s){cout << "string& operator=(const string& s) -- 深拷贝" << endl;if (this != &s){_str[0] = '\0';_size = 0;reserve(s._capacity);for (auto ch : s){push_back(ch);}}return *this;}// 移动赋值string& operator=(string&& s){cout << "string& operator=(string&& s) -- 移动赋值" << endl;swap(s);return *this;}~string(){cout << "~string()" << endl;delete[] _str;_str = nullptr;}char& operator[](size_t pos){assert(pos < _size);return _str[pos];}void reserve(size_t n){if (n > _capacity){char* tmp = new char[n + 1];if (_str){strcpy(tmp, _str);delete[] _str;}_str = tmp;_capacity = n;}}void push_back(char ch){if (_size >= _capacity){size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newcapacity);}_str[_size] = ch;++_size;_str[_size] = '\0';}//string operator+=(char ch)string& operator+=(char ch){push_back(ch);return *this;}const char* c_str() const{return _str;}private:char* _str = nullptr;size_t _size = 0;size_t _capacity = 0; // 不包含最后做标识的\0};
}
针对移动构造函数和移动赋值运算符重载有一些需要注意的点如下:
如果你没有自己实现移动构造函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中的任意一个。那么编译器会自动生成一个默认移动构造。默认生成的移动构造函数,对于内置类型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动构造,如果实现了就调用移动构造,没有实现就调用拷贝构造。
class Person
{
public:Person(const char* name = "", int age = 0):_name(name),_age(age){}
private:string _name;int _age;
};int main()
{Person s1("Peter",18);Person s2 = s1;Person s3 = move(s1);return 0;
}
为什么这里的条件怎么苛刻呢?
因为如果一个类需要显示写析构说明有资源需要释放,那么通常就要写析构函数,拷贝构造,拷贝赋值运算重载,对资源进行管理,假如一个类是由自定义类型和内置类型构成的,对于内置类型不需要进行资源管理,只要完成值拷贝就可以了,而且要不用释放资源,对于自定义类型,如果由资源需要管理,我们只需要调用它对应写的函数即可,这样就不用我们单独写了,例如:Person类。
所以这里的条件是合理的。
如果你没有自己实现移动赋值重载函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中的任意一个,那么编译器会自动生成一个默认移动赋值。
默认生成的移动构造函数,对于内置类型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动赋值,如果实现了就调用移动赋值,没有实现就调用拷贝赋值。(默认移动赋值跟上面移动构造完全类似)如果你提供了移动构造或者移动赋值,编译器不会自动提供拷贝构造和拷贝赋值。
class Person
{
public:Person(const char* name = "", int age = 0):_name(name),_age(age){}
private:string _name;int _age;
};int main()
{Person s1("Peter",18);Person s2;s2 = s1;Person s3;s3 = move(s1);return 0;
}
如果你提供了移动构造或者移动赋值,编译器不会自动提供拷贝构造和拷贝赋值。
class Person
{
public:Person(const char* name = "", int age = 0):_name(name),_age(age){}Person(Person&& s) = default;
private:string _name;int _age;
};int main()
{Person s1("Peter",18);Person s2 = s1;//errreturn 0;
}
因为如果我们不写拷贝构造,编译器就会生成默认的拷贝构造,对于内置类型完成值拷贝,对应自定义类型对调用其对应的拷贝构造,但是如果我们显示写了移动构造,编译器会把移动构造当做拷贝构造的一种,就不会生成默认的拷贝构造,只能完成右值对应的拷贝。
强制生成默认函数的关键字default:
C++11可以让你更好的控制要使用的默认函数。假设你要使用某个默认的函数,但是因为一些原因这个函数没有默认生成。比如:我们提供了拷贝构造,就不会生成移动构造了,那么我们可以使用default关键字显示指定移动构造生成。
class Person
{
public:Person(const char* name = "", int age = 0):_name(name), _age(age){}Person(const Person& p):_name(p._name),_age(p._age){}Person(Person&& p) = default;
private:string _name;int _age;
};
禁止生成默认函数的关键字delete:
如果能想要限制某些默认函数的生成,在C++98中,是该函数设置成private,并且只声明补丁已,这样只要其他人想要调用就会报错。在C++11中更简单,只需在该函数声明加上=delete即可,该语法指示编译器不生成对应函数的默认版本,称=delete修饰的函数为删除函数。
class Person
{
public:Person(const char* name = "", int age = 0):_name(name),_age(age){}//Person(const Person& s) = delete;Person(Person&& s) = delete;
private:string _name;int _age;
};
我们只需要禁用拷贝构造或者移动构造中的一个另一个就不会自动生成,赋值重载也是同样的道理。
可变参数模板
C++11的新特性可变参数模板能够让您创建可以接受可变参数的函数模板和类模板。
下面就是一个基本可变参数的函数模板
// Args是一个模板参数包,args是一个函数形参参数包
// 声明一个参数包Args...args,这个参数包中可以包含0到任意个模板参数。
template <class ...Args>
void ShowList(Args... args)
{cout << sizeof...(args) << endl;
}int main()
{ShowList();ShowList('x');ShowList('x', 'y');
}
上面的参数args前面有省略号,所以它就是一个可变模版参数,我们把带省略号的参数称为“参数包”,它里面包含了0到N(N>=0)个模版参数。我们无法直接获取参数包args中的每个参数的,只能通过展开参数包的方式来获取参数包中的每个参数。
递归函数方式展开参数包
void ShowList()
{cout << endl;
}template <class T, class ...Args>
void ShowList(const T& val, Args... args)
{cout << val << " ";ShowList(args...);
}int main()
{ShowList();ShowList('x');ShowList('x', 'y');ShowList(1,'x', 'y');
}
逗号表达式展开参数包
template <class T>
void PrintArg(T t)
{cout << t << " ";
}template <class ...Args>
void ShowList(Args... args)
{int arr[] = { (PrintArg(args),0)... };cout << endl;
}int main()
{ShowList('x');ShowList('x', 'y');ShowList(1,'x', 'y');
}
也可以这样写:
template <class T>
int PrintArg(T t)
{cout << t << " ";return 0;
}template <class ...Args>
void ShowList(Args... args)
{int arr[] = { PrintArg(args)... };cout << endl;
}int main()
{ShowList('x');ShowList('x', 'y');ShowList(1,'x', 'y');
}
实际编译器编译推演生成了一下代码
template <class T>
int PrintArg(T t)
{cout << t << " ";return 0;
}void ShowList(int a,char b,char c)
{int arr[] = { PrintArg(a),PrintArg(b),PrintArg(c)};cout << endl;
}int main()
{ShowList(1,'x', 'y');
}
STL容器中的empalce相关接口函数:
template <class ...Args>
void emplace_back(Args ...args)
{//...
}
首先我们看到的emplace系列的接口,支持模板的可变参数,并且万能引用。那么emplace系列接口的优势到底在哪里呢?
int main()
{list<bit::string> mylist;//没有区别string s1("1111");mylist.push_back(s1);mylist.emplace_back(s1);cout << endl;string s2("2222");mylist.push_back(move(s1));mylist.emplace_back(move(s2));//有区别cout << endl;//先构造临时对象 + 移动构造mylist.push_back("1111");//直接构造mylist.emplace_back("1111");
}
模拟实现emplace_back
#pragma once
#include <assert.h>#include <iostream>using namespace std;namespace hb
{template <class T>struct ListNode{ListNode<T>* _prev;ListNode<T>* _next;T _data;ListNode(const T& data = T()):_prev(nullptr), _next(nullptr), _data(data){}ListNode(T&& data):_prev(nullptr), _next(nullptr), _data(move(data)){}template <class ...Args>ListNode(Args&&... args): _prev(nullptr), _next(nullptr), _data(forward<Args>(args)...){}};template <class T,class Ref,class Ptr>struct ListIterator{typedef ListNode<T> Node;Node* _node;typedef ListIterator<T,Ref,Ptr> self;ListIterator(Node* node):_node(node){}self& operator++(){_node = _node->_next;return *this;}self operator++(int){self tmp(*this);_node = _node->_next;return tmp;}self& operator--(){_node = _node->_prev;return *this;}self operator--(int){self tmp(*this);_node = _node->_prev;return tmp;}Ref operator*(){return _node->_data;}bool operator!=(const self& node){return _node != node._node;}bool operator==(const self& node){return _node == node._node;}Ptr operator->(){return &_node->_data;}};template <class T>struct ListConstIterator{typedef ListNode<T> Node;Node* _node;typedef ListConstIterator<T> self;ListConstIterator(Node* node):_node(node){}self& operator++(){_node = _node->_next;return *this;}self operator++(int){self tmp(*this);_node = _node->_next;return tmp;}self& operator--(){_node = _node->_prev;return *this;}self operator--(int){self tmp(*this);_node = _node->_prev;return tmp;}const T& operator*(){return _node->_data;}bool operator!=(const self& node){return _node != node._node;}bool operator==(const self& node){return _node == node._node;}const T* operator->(){return &_node->_data;}};template <class T>class list{typedef ListNode<T> Node;public:typedef ListIterator<T,T&,T*> iterator;typedef ListIterator<T,const T&,const T*> const_iterator;//typedef ListConstIterator<T> const_iterator;iterator begin(){return iterator(_head->_next);}const_iterator begin() const{return const_iterator(_head->_next);}iterator end(){return iterator(_head);}const_iterator end() const{return const_iterator(_head);}void empty_list(){_head = new Node;_head->_prev = _head;_head->_next = _head;}list(){empty_list();}~list(){clear();delete _head;_head = nullptr;}void clear(){iterator it = begin();while (it != end()){//it = erase(it);erase(it++);}}/*list(const list<T>& lt){empty_list();for (const auto& e : lt){push_back(e);}}*/void swap(list<T>& tmp){std::swap(_head, tmp._head);}template <class Iterator>list(Iterator first, Iterator last){empty_list();//不加会出问题while (first != last){push_back(*first);++first;}}list(const list<T>& lt){empty_list();list<T> tmp(lt.begin(), lt.end());swap(tmp);}list<T>& operator=(list<T> tmp){swap(tmp);return *this;}void push_back(const T& x){/*Node* tail = _head->_prev;Node* newnode = new Node(x);newnode->_prev = tail;newnode->_next = _head;tail->_next = newnode;_head->_prev = newnode;*/insert(end(),x);}void push_back(T&& x){/*Node* tail = _head->_prev;Node* newnode = new Node(x);newnode->_prev = tail;newnode->_next = _head;tail->_next = newnode;_head->_prev = newnode;*/insert(end(), move(x));}template <class ...Args>void emplace_back(Args&& ...args){insert(end(), forward<Args>(args)...);}void push_front(const T& x){insert(begin(),x);}void pop_back(){erase(--end());}void pop_front(){erase(begin());}iterator insert(iterator pos, const T& x){Node* node = pos._node;Node* prev = node->_prev;Node* newnode = new Node(x);newnode->_prev = prev;newnode->_next = node;prev->_next = newnode;node->_prev = newnode;return iterator(newnode);}template<class ...Args>iterator insert(iterator pos, Args&&... args){Node* node = pos._node;Node* prev = node->_prev;Node* newnode = new Node(forward<Args>(args)...);newnode->_prev = prev;newnode->_next = node;prev->_next = newnode;node->_prev = newnode;return iterator(newnode);}iterator insert(iterator pos, T&& x){Node* node = pos._node;Node* prev = node->_prev;Node* newnode = new Node(move(x));newnode->_prev = prev;newnode->_next = node;prev->_next = newnode;node->_prev = newnode;return iterator(newnode);}iterator erase(iterator pos){assert(pos != end());Node* del = pos._node;Node* prev = del->_prev;Node* next = del->_next;prev->_next = next;next->_prev = prev;return iterator(next);}bool empty() const{return _head == _head->_next;}T& front(){return _head->_next->_data;}const T& front() const{return _head->_next->_data;}T& back(){return _head->_prev->_data;}const T& back() const{return _head->_prev->_data;}size_t size() const{size_t count = 0;Node* pcur = _head->_next;while (pcur != _head){count++;pcur = pcur->_next;}return count;}void resize(size_t newsize, const T& data = T()){size_t oldsize = size();if (newsize <= oldsize){while (newsize != oldsize){pop_back();oldsize--;}}else{while (oldsize != newsize){push_back(data);oldsize++;}}}private:Node* _head;};
}
代码测试:
int main()
{hb::list<string> mylist;//没有区别string s1("1111");mylist.push_back(s1);mylist.emplace_back(s1);cout << endl;string s2("2222");mylist.push_back(move(s1));mylist.emplace_back(move(s2));//有区别cout << endl;//先构造临时对象 + 移动构造mylist.push_back("1111");//直接构造mylist.emplace_back("1111");
}
相关文章:
C++新增的类功能和可变参数模板
C新增的类功能和可变参数模板 新的类功能默认成员函数 可变参数模板模拟实现emplace_back 🌏个人博客主页: 个人主页 新的类功能 默认成员函数 原来C类中,有6个默认成员函数: 构造函数析构函数拷贝构造函数拷贝赋值重载取地址…...
redo log 日志 与 undo log 日志工作原理
目录标题 1. redo log 日志2. undo log 日志3.总结 1. redo log 日志 redo log日志是 MySQL 数据中的重要日志之一,其本质是物理日志,存放于 数据库的数据目录中 ,名称为: ib_logfile 。它的功能主要是用于存放脏数据的日志&…...
go语言结构体与json数据相互转换
本博文简要介绍go语言结构体如何与json格式化字符串相互转换。 文章目录 go语言结构体转换为json数据json数据转换为go结构体 go语言结构体转换为json数据 type Person struct {Name string json:"name"Age int json:"age"Hobbies []strin…...
jenkins 自动化部署Springboot 项目
一、安装docker 1.更新yum命令 yum -y update2.查看机器有残留的docker服务,有就卸载干净 查看docker 服务 rpm -qa |grep docker卸载docker sudo yum remove docker-ce docker-ce-cli containerd.io sudo rm -rf /var/lib/docker sudo rm -rf /var/lib/contai…...
使用xml发送国际短信(smspro)【吉尔吉斯斯坦】
//使用xml格式发送国外短信验证码【吉尔吉斯斯坦】官网:https://smspro.nikita.kg/ public function api_test($data,$user){$url "http://smspro.nikita.kg/api/message";$code 123456 ;$content Your verification code 123456, this verification …...
springmvc-springsecurity-redhat keycloak SAML2 xml实现
环境准备: jdk17 redhat keycloak 24 spring security 6 参照文档: 红帽KeyCloak:Red Hat build of Keycloak | Red Hat Product Documentation 入门指南:入门指南 | Red Hat Product Documentation 服务器管理指南&#x…...
【K8S系列】Kubernetes Pod节点CrashLoopBackOff 状态及解决方案详解【已解决】
在 Kubernetes 中,Pod 的状态为 CrashLoopBackOff 表示某个容器在启动后崩溃,Kubernetes 尝试重启该容器,但由于持续崩溃,重启的间隔时间逐渐增加。下面将详细介绍 CrashLoopBackOff 状态的原因、解决方案及相关命令的输出解释。 …...
Linux: Shell编程入门
Shell 编程入门 1 ) Shell 概念 shell 是 在英语中 壳, 外壳的意思可以把它想象成嵌入在linux这样的操作系统里面的一个微型的编程语言不像C语言, C 或 Java 等编程语言那么完整,它可以帮我们完成很多自动化任务例如保存数据监测系统的负载等等,我们同样…...
python爬虫实战案例——抓取B站视频,不同清晰度抓取,实现音视频合并,超详细!(内含完整代码)
文章目录 1、任务目标2、网页分析3、代码编写 1、任务目标 目标网站:B站视频(https://www.bilibili.com/video/BV1se41117WP/?vd_sourcee8e376ccbc5aa4cfd88e6a7917adfd1a),用于本文测验 要求:抓取该网址下的视频&…...
容灾与云计算概念
基础知识容灾备份——备份技术系统架构与备份网络方案-CSDN博客 SAN,是storage area network的简称,翻译过来就是存储区域网络。 顾名思义,SAN首先是一个网络,其次它是关于存储的,区域则是指服务器和存储资…...
基于 Python 的自然语言处理系列(44):Summarization(文本摘要)
在这一部分中,我们将探讨如何使用 Transformer 模型将长文档压缩为摘要,这个任务被称为文本摘要。文本摘要是 NLP 领域中最具挑战性的任务之一,因为它需要理解长篇文本并生成连贯的总结,捕捉文档中的核心主题。然而,当…...
RabbitMQ安装部署
安装Erlang 由于RabbitMQ是用Erlang语言编写的,所以在安装RabbitMQ之前需要安装Erlang 安装依赖 [rootpro-ex ~]yum install make gcc gcc-c build-essential openssl openssl-devel unixODBC unixODBC-devel kernel-devel m4 ncurses-devel设置Eralng的存储库 […...
智联招聘×Milvus:向量召回技术提升招聘匹配效率
01. 业务背景 在智联招聘平台,求职者和招聘者之间的高效匹配至关重要。招聘者可以发布职位寻找合适的人才,求职者则通过上传简历寻找合适的工作。在这种复杂的场景中,我们的核心目标是为双方提供精准的匹配结果。在搜索推荐场景下,…...
unplugin-auto-import 库作用
unplugin-auto-import是一个 Vite、Webpack 和 Rollup 的插件。 一、自动导入模块 1. 减少手动导入 在 JavaScript 和 TypeScript 项目中,它可以自动检测并导入常用的模块和函数,无需手动在每个文件中进行导入操作。这大大减少了代码中的重复性导入语…...
【Multisim14.0正弦波>方波>三角波】2022-6-8
缘由有没有人会做啊Multisim14.0-其他-CSDN问答参考方波、三角波、正弦波信号产生 - 豆丁网...
vue3纯前端验证码示例
前言 验证码的用途:通过要求用户输入一串难以被机器自动识别的字符或图像,有效阻止恶意用户或脚本通过暴力破解方式尝试登录账户。验证码的分类:常见的验证码有短信、文本、图形等,安全度越高,依赖的插件或服务也越多…...
招聘程序员
全栈总监❤️golang❤️UI设计师 ☀️前端☀️Nodejs工☀️平面设计☀️PHP工 ☀️安卓❤️Flutter❤️运维☀️爬虫 公司福利: ☃️ 带薪年假、年终奖、13k-18k薪 🏩 内宿 2人/间或外宿可补助 💵 转正绩效 ✨节日礼金:生日礼金…...
Android 判断手机放置的方向
#1024程序员节|征文# 文章目录 前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 需求 老板:我有个手持终端,不能让他倒了,当他倒或者倾斜的时候要发出报警; 程序猿:我这..... 老板…...
Telegram机器人的手机部署
目的 一直有读 epub 电子书的习惯,摘录段落复制下来段落很难看,把自己写的排版器的逻辑复制下来,写成了一个排版机器人所有发给机器人的文字,都会经过排版,后转发到读书频道 前提 本来最好方法是直接把机器人架在服…...
ffmpeg视频滤镜: 色温- colortemperature
滤镜简述 colortemperature 官网链接 》 FFmpeg Filters Documentation 这个滤镜可以调节图片的色温,色温值越大显得越冷,可以参考一下下图: 咱们装修的时候可能会用到,比如选择灯还有地板的颜色的时候,选暖色调还是…...
Django+Vue全栈开发项目入门(二)
Vue是一款用于构建用户界面的JavaScript渐进式框架,它基于标准HTML、CSS和JavaScript构建,并提供了一套声明式的、响应式的、组件化的编程模型,有助于高效地开发用户界面。 环境准备 安装Node.js:Vue项目的构建和运行依赖于Node…...
【ubuntu改源】
ubuntu改源 备份原始源查看ubuntu发行版本arm64 noble版本的源vim修改源更新系统软件源 备份原始源 sudo cp /etc/apt/sources.list /etc/apt/sources.list.disabled查看ubuntu发行版本 lsb_release -aarm64 noble版本的源 清华源 vim修改源 esc :1,$d # 删除所有# 默认注…...
SQLI LABS | Less-9 GET-Blind-Time based-Single Quotes
关注这个靶场的其它相关笔记:SQLI LABS —— 靶场笔记合集-CSDN博客 0x01:过关流程 输入下面的链接进入靶场(如果你的地址和我不一样,按照你本地的环境来): http://localhost/sqli-labs/Less-9/ 靶场提示 …...
【小白学机器学习24】 用例子来比较:无偏估计和有偏估计
目录 1 关于无偏估计 1.1 无偏估计的定义 2 原始数据 2.1 假设我们是上帝,我们能创造一个总体/母体 population 2.2 按尽量随机取样的原则去取1个随机样本 sample1 3 一个关于无偏估计的理解 3.1 接着上面的总体和样本 sample1 3.2 左边的计算,期…...
C++在实际项目中的应用第二节:C++与网络编程
第五章:C在实际项目中的应用 第二节:C与网络编程 1. TCP/IP协议详解与C实现 TCP/IP(传输控制协议/互联网协议)是现代互联网通信的基础协议。理解 TCP/IP 协议对于开发网络应用至关重要。本节将详细介绍 TCP/IP 协议的工作原理以…...
依赖关系是危险的
依赖, 我们需要它们,但如何有效安全地使用它们?在本周的节目中,Kris 与 Ian 和 Johnny 一起讨论了 polyfill.io 供应链攻击、Go 中依赖管理和使用的历史,以及 Go 谚语“一点复制胜过一点依赖”。当然,我们用一些不受欢…...
ipguard与Ping32如何加密数据防止泄露?让企业信息更安全
在信息化时代,数据安全已成为企业运营的重中之重。数据泄露不仅会导致经济损失,还可能损害企业声誉。因此,选择合适的数据加密工具是保护企业敏感信息的关键。本文将对IPGuard与Ping32这两款加密软件进行探讨,了解它们如何有效加密…...
gitlab 的备份与回复
一、gitlab备份 1.确定备份目录 gitlab 默认的备份目录为/var/opt/gitlab/backups,可通过配置gitlab.rb配置文件进行修改,如: [rootlocalhost ~]# vim /etc/gitlab/gitlab.rb #若要修改备份文件的存储目录话,打开下面选项的注释…...
创建型模式-----建造者模式
目录 背景: 构建模式UML 代码示例 房子成品: 构建器抽象: 具体构建器: 建筑师: 测试部…...
威胁 Windows 和 Linux 系统的新型跨平台勒索软件:Cicada3301
近年来,网络犯罪世界出现了新的、日益复杂的威胁,能够影响广泛的目标。 这一领域最令人担忧的新功能之一是Cicada3301勒索软件,最近由几位网络安全专家进行了分析。他们有机会采访了这一危险威胁背后的勒索软件团伙的成员。 Cicada3301的崛…...
网站设置万事达u卡/百度官网认证价格
2019-02-14 【小记】 RO段、RW段和ZI段 --Image$$??$$Limit 含义(zz)转载于:https://www.cnblogs.com/skullboyer/p/10373972.html...
国内设计网站公司网站/上海百度seo牛巨微
TreeMap是jdk中基于红黑树的一种map实现。HashMap底层是使用链表法解决冲突的哈希表,LinkedHashMap继承自HashMap,内部同样也是使用链表法解决冲突的哈希表,但是额外添加了一个双向链表用于处理元素的插入顺序或访问访问。 既然TreeMap底层使…...
柳北网站制作/网站功能优化
Microsoft Visual Studio 2010 的项目为件改为Microsoft Visual Studio 2015默认打开 2010 的Solution (.Sln) file Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 --默认打开的版本IDE Geovin Du 涂聚文 注释 Project("{FAE04EC…...
新闻网站备案的前置条件/seo网站关键词优化哪家好
报错:Cant update: no tracked branch 我们之前的分支是drome,然后删除了这个分支,换到了另一个分支上面去了,所以出现了这个问题。 解决办法: 0:点击VCS->Git->Rebase 1:然后选择相应的分…...
网站登录账号密码保存在哪里/免费推广网站大全下载安装
中国汽车业已成为全球第一市场,标志着中国汽车产业进入了白热化竞争时代,因此,人们对汽车的操控性,安全性,易用性,舒适性,以及智能化要求也越来越高,更大的空间需求和更多的零部件因…...
wordpress无法找到页面/百度服务电话在线人工
qtz中如果画曲线涉及到旋转会使用矩阵变幻,这儿有一个秘诀,就是先平移到旋转中心,在设置旋转角度,然后平移到旋转中心的负方向,最后就可以按需求画出来 p.drawRect(QRect(100,100,200,200));p.translate(200,200);p.ro…...