【C++初阶】vector的模拟实现
大家好我是沐曦希💕
文章目录
- 一、前言
- 二、无参构造&析构
- 三、基础接口
- 1.empty和clear
- 2.size和capacity
- 3.[]和iterator
- 四、reserve和resize
- 五、尾插尾删
- 六、其他构造
- 1.迭代器区间构造
- 2.拷贝构造
- 七、memcpy问题
- 八、完整代码
一、前言
在模拟实现容器时候,我们需要的不是造一个更好的轮子,而是在了解原理更好理解和运用容器。
那么通过查看源码,抽出vector容器主题框架:
template <class T, class Alloc = alloc>
class vector {typedef T value_type;typedef value_type* iterator;typedef const value_type* const_iterator;
protected:iterator start;iterator finish;iterator end_of_storage;
}
本质上与T*a,size_t size,size_t capacity是类似的:
对于size = _finish - _start
对于capacity = _endofstorage-_start
二、无参构造&析构
- 无参构造
初始化值为空。
vector():_start(nullptr),_finish(nullptr),_endofstarge(nullptr)
{}
- 析构
~vector()
{delete[] _start;_start = _finish = _endofstarge = nullptr;
}
三、基础接口
1.empty和clear
- empty
bool empty()
{return _finish == _start;
}
- clear
void clear()
{_finish = _start; //这里可不能置为nullptr
}
2.size和capacity
- size
int size() const
{return _finish - _start;
}
-capacity
int capacity() const
{return _endofstarge - _start;
}
加const是让const类对象和非const类对象都能调用
3.[]和iterator
这里提供const和非const两个版本,加const是只可读,不能更改,不加const是可读可写。
- []
T& operator[](const size_t pos)
{assert(pos < size());return _start[pos];
}
const T& operator[](const size_t pos)
{assert(pos < size())return _start[pos];
}
- iterator
同理普通迭代器和const迭代器版本,同理,范围for循环此时也是可以实现的:
typedef T* iterator;
typedef const T* const_iterator;
iterator begin()
{return _start;
}
iterator end()
{return _finish;
}
const_iterator beign()
{return _start;
}
const_iterator end()
{return _finish;
}
四、reserve和resize
- reserve
reserve最大问题是深拷贝,开辟新空间进行赋值的时候如果直接使用memcpy是浅拷贝。
void reserve(size_t n)
{if (n > capacity()){int Oldsize = size();//size需要保存,方便更改_finsihT* tmp = new T[n];//为空不需要拷贝if (_start){for (size_t i = 0; i < Oldsize; ++i){tmp[i] = _start[i];}}_start = tmp;_finish = _start + Oldsize;_endofstarge = _start + n;tmp = nullptr;}
}
- size()要保存
因为size = _finish - _start,_start已经改变了。而_finish没有改变,那么size就是一个任意数了,不再是原来的size了,就需要在开始时候用Oldsize进行存储size
- 使用memcpy问题
memcpy拷贝数据是按字节来拷贝的属于浅拷贝,对于需要在堆开辟空间的自定义类型存在问题,多次释放同一块空间将导致程序崩溃
vector<vector<int>> vv; vector<int> v(4, 1); //复用push_back尾插 vv.push_back(v); vv.push_back(v); vv.push_back(v); vv.push_back(v); //需要扩容成2倍 vv.push_back(v); for (size_t i = 0; i < vv.size(); i++) {for (size_t j = 0; j < vv[i].size(); j++){cout << vv[i][j] << " ";}cout << endl; }
- resize
用n个数据初始化vector,那么就要用n和size进行比对,分情况讨论:
1、当n大于当前的size时,将size扩大到n,扩大的数据为val,若val未给出,则默认为容器所存储类型的默认构造函数所构造出来的值。
2、当n小于当前的size时,将size缩小到n。
根据resize函数的规则,进入函数我们可以先判断所给n是否小于容器当前的size,若小于,则通过改变_finish的指向,直接将容器的size缩小到n即可,否则先判断该容器是否需要增容,然后再将扩大的数据赋值为val即可。
void resize(size_t n, const T& value = T())
{if (n < size()){_finish = _start + n;}reserve(n); // reserve对于n<capacity是不会做任何事情的for (size_t i = 0; i < n - size(); ++i){_finish[i] = value;}_finish = _start + n;
}
resize的参数初始化值为T类型的构造,这里可不能直接初始化为0,要是T是自定义类型呢?是vector呢?所以这里如果T是vector的化调用的就是vector的构造函数。另外,这里还需要注意的一点是:构造vector的时候是匿名对象,匿名对象具有常性,不可修改所以要加上const修饰。对于内置类型比如int,都是有构造函数的
五、尾插尾删
void push_back(const T& value)
{if (_finish == _endofstarge){size_t newCapacity = capacity() == 0 ? 4 : capacity() * 2;reserve(newCapacity);}*_finish = value;++_finish;
}
void pop_back()
{assert(_start < _finish);if (_finish > _start){--_finish;}
}
六、其他构造
1.迭代器区间构造
vector(InputIterator first, InputIterator last):_start(nullptr),_finish(nullptr),_endofstarge(nullptr)
{while (first != last){push_back(*first);//int不能解引用++first;}
}
类模板的成员函数可以是函数模板,使之可以是任意类型的迭代器区间,包括了自身的迭代器区间构造
另外,初始化列表全部初始化为nullptr,没有初始化就是随机值,出现野指针
2.拷贝构造
初始化列表全都要初始化为nullptr,否则就是随机值
//写法一
vector(const vector<T>& v):_start(nullptr), _finish(nullptr), _endofstarge(nullptr)
{reserve(v.capacity());for (const auto& e : v){push_back(e);}
}
//写法二
void swap(vector<T>& v)
{std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_endofstarge, v._endofstarge);
}
vector(const vector<T>& v):_start(nullptr), _finish(nullptr), _endofstarge(nullptr)
{vector<T> tmp(v.begin(), v._end());swap(tmp);
}
- 赋值重载
可以复用拷贝构造
//缺陷是不能自己拷贝自己
vector& operator=(vector<T> v)
{swap(v);return *this;
}
这种写法就是有一个小问题:如果是自己拷贝自己呢?加个判断?没用,因为此时已经传值传参过来了,加个判断没啥意义了。但是这个问题不大,我们允许存在,平时自己也很少自己赋值自己。
另外,这里是传值调用,有人会说了:传引用也可以啊,此时如果是引用的话,v2赋值给v1,v1不是v2的拷贝,直接把v2换成了v1,v1换给了v2,v2本身已经发生变化了,这不是赋值了。
七、memcpy问题
如果拷贝的是内置类型的元素,memcpy即高效又不会出错,但如果拷贝的是自定义类型元素,并且自定义类型元素中涉及到资源管理时,就会出错,因为memcpy的拷贝实际是浅拷贝,指向同一块空间,假设我们仍然在reserve接口中使用memcpy进行拷贝:
int main()
{bite::vector<bite::string> v;v.push_back("1111");v.push_back("2222");v.push_back("3333");return 0;
}
问题分析:
- memcpy是内存的二进制格式拷贝,将一段内存空间中内容原封不动的拷贝到另外一段内存空间中
- 如果拷贝的是内置类型的元素,memcpy既高效又不会出错,但如果拷贝的是自定义类型元素,并且自定义类型元素中涉及到资源管理时,就会出错,因为memcpy的拷贝实际是浅拷贝。
结论:如果对象中涉及到资源管理时,千万不能使用memcpy进行对象之间的拷贝,因为memcpy是浅拷贝,否则可能会引起内存泄漏甚至程序崩溃。
八、完整代码
- vector.h
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace lj
{template<class T>class vector{public:// Vector的迭代器是一个原生指针typedef T* iterator;typedef const T* const_iterator;iterator begin(){return _start;}iterator end(){return _finish;}const_iterator cbegin() const{return _start;}const_iterator cend() const{return _finish;}iterator rbegin(){return _finish;}iterator rend(){return _start;}const_iterator rbegin() const{return _finish;}const_iterator rend() const{return _start;}// construct and destroyvector():_start(nullptr), _finish(nullptr), _endofstorage(nullptr){}vector(int n, const T& value = T()):_start(nullptr), _finish(nullptr), _endofstorage(nullptr){reserve(n);for (size_t i = 0; i < n; ++i){push_back(value);}}template<class InputIterator>vector(InputIterator first, InputIterator last){while (first != last){push_back(*first);first++;}}vector(const vector<T>& v){int* tmp = new T[v.capacity()];for (size_t i = 0; i < v.size(); ++i){tmp[i] = v[i];}_start = tmp;_finish = _start + v.size();_endofstorage = _start + v.capacity;}vector<T>& operator=(vector<T> v){vector tmp(v);_start = _finish = _endofstorage = nullptr;swap(_start, tmp._start);swap(_finish, tmp._finish);swap(_endofstorage, tmp._endofstorage);}~vector(){delete[] _start;_start = _finish = _endofstorage = nullptr;}// capacitysize_t capacity() const{return _endofstorage - _start;}size_t size() const{return _finish - _start;}void reserve(size_t n){if (n > capacity()){int Oldsize = size();T* tmp = new T[n];if (_start){for (size_t i = 0; i < size(); ++i){tmp[i] = _start[i];}}_start = tmp;_finish = _start + Oldsize;_endofstorage = _start + n;tmp = nullptr;}}void resize(size_t n, const T& value = T()){if (n <= size()){_finish = _start + n;}reserve(n);for (size_t i = 0; i < n - size(); ++i){_finish[i] = value;}_finish = _start + n;}///access///T& operator[](size_t pos){assert(pos < size());return _start[pos];}const T& operator[](size_t pos)const{assert(pos < size());return _start[pos];}///modify/void push_back(const T& x){if (_finish == _endofstorage){int newCapacity = capacity() == 0 ? 4 : capacity() * 2;reserve(newCapacity);}*_finish = x;++_finish;}void pop_back(){assert(_start < _finish);if (_finish > _start){--_finish;}}void swap(vector<T>& v){vector tmp;tmp._start = _start;_start = v._start;v._start = tmp._start;tmp._finish = _finish;_finish = v._finish;v._finish = tmp._finish;tmp._endofstorage = _endofstorage;_endofstorage = v._endofstorage;v._endofstorage = tmp._endofstorage;tmp._start = tmp._finish = tmp._endofstorage = nullptr;}iterator insert(iterator pos, const T& x){assert(pos >= _start);assert(pos <= _finish);size_t Olddel = pos - _start;if (_finish == _endofstorage){size_t newCapacity = capacity() == 0 ? 4 : capacity() * 2;reserve(newCapacity);}pos = _start + Olddel;auto it = _finish;while (it > pos){*it = *(it - 1);it--;}*pos = x;++_finish;return pos;}iterator erase(iterator pos){assert(pos >= _start);assert(pos < _finish);auto it = pos;while (it < _finish){(*it) = *(it + 1);it++;}--_finish;return pos;}private:iterator _start; // 指向数据块的开始iterator _finish; // 指向有效数据的尾iterator _endofstorage; // 指向存储容量的尾};void test_vector1(){vector<int> v1(10, 2);for (auto e : v1){cout << e << " ";}cout << endl;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);for (auto e : v1){cout << e << " ";}cout << endl;v1.reserve(20);cout << v1.size() << endl;cout << v1.capacity() << endl;vector<int> v2;for (auto e : v2){cout << e << " ";}cout << endl;cout << v2.size() << endl;cout << v2.capacity() << endl;}void test_vector2(){vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);v1.push_back(5);for (auto e : v1){cout << e << " ";}cout << endl;vector<int> v2(v1.rend(), v1.rbegin());for (auto e : v2){cout << e << " ";}cout << endl;cout << v2.size() << endl;cout << v2.capacity() << endl;v2.resize(10, 1);for (auto e : v2){cout << e << " ";}cout << endl;cout << v2.size() << endl;cout << v2.capacity() << endl;v2.resize(5);for (auto e : v2){cout << e << " ";}cout << endl;cout << v2.size() << endl;cout << v2.capacity() << endl;v2.resize(15, 2);vector<int>::iterator it = v2.begin();while (it < v2.end()){cout << (*it) << " ";++it;}cout << endl;for (size_t i = 0; i < v2.size(); ++i){cout << v2[i] << " ";}cout << endl;v2.pop_back();for (auto e : v2){cout << e << " ";}cout << endl;cout << v2.size() << endl;cout << v2.capacity() << endl;v2.pop_back();v2.pop_back();v2.pop_back();v2.pop_back();v2.pop_back();v2.pop_back();v2.pop_back();v2.pop_back();v2.pop_back();for (auto e : v2){cout << e << " ";}cout << endl;cout << v2.size() << endl;cout << v2.capacity() << endl;v2.swap(v1);cout << "------------------ v1 --------------------" << endl;for (auto e : v1){cout << e << " ";}cout << endl;cout << v1.size() << endl;cout << v1.capacity() << endl;cout << "------------------ v2 --------------------" << endl;for (auto e : v2){cout << e << " ";}cout << endl;cout << v2.size() << endl;cout << v2.capacity() << endl;v1.resize(15);cout << v1.size() << endl;cout << v1.capacity() << endl;v1.insert(v1.begin(), 1);v1.insert(v1.end(), 1);for (auto e : v1){cout << e << " ";}cout << endl;cout << v1.size() << endl;cout << v1.capacity() << endl;}
}
相关文章:
【C++初阶】vector的模拟实现
大家好我是沐曦希💕 文章目录一、前言二、无参构造&析构三、基础接口1.empty和clear2.size和capacity3.[]和iterator四、reserve和resize五、尾插尾删六、其他构造1.迭代器区间构造2.拷贝构造七、memcpy问题八、完整代码一、前言 在模拟实现容器时候࿰…...
微信小程序、小游戏的流量主一般可以赚多少钱?
本篇文章主要科普小程序、小游戏流量主一般赚钱的实际情况,通过在下长期运营的经验汇总而成。 日期:2023年2月26日 作者:任聪聪 小程序、小程序满1000用户后即可开通流量主,但实际上很多人并没有传说中的那种日赚几千的流量收入的…...
jni-Demo-基于linux(c++ java)
跑一个jni 的最简单的Demo需要提前准备 VsCode 编译器、win10下,vscode中集成linux操作系统、c编译器(gcc、g),java编译器(jdk1.8)参考:https://mangocool.com/1653030123842.htmlJniDemo类&…...
指针的进阶——(1)
本次讲解重点: 1、字符指针 2、数组指针 3、指针数组 4、数组传参和指针传参 5、函数指针 关于指针这个知识点的主题,我们在前面已经初级阶段已经对指针有了大致的理解和应用了。我们知道了指针的概念: 1、指针就是地址,但口…...
电商平台的促销活动如何抵御大流量的ddos攻击
每一次活动大促带来的迅猛流量,对技术人而言都是一次严峻考验。如果在活动期间遭受黑产恶意 DDoS 攻击,无疑是雪上加霜。电商的特性是业务常态下通常不会遭受大流量 DDoS 攻击,且对延迟敏感,因此只需要在活动期间按需使用 DDoS 防…...
代码随想录-48-104. 二叉树的最大深度
目录前言题目1.层序迭代思路2. 本题思路分析:3. 算法实现4. pop函数的算法复杂度5. 算法坑点前言 在本科毕设结束后,我开始刷卡哥的“代码随想录”,每天一节。自己的总结笔记均会放在“算法刷题-代码随想录”该专栏下。 代码随想录此题链接 …...
【Vue3源码】第六章 computed的实现
【Vue3源码】第六章 computed的实现 上一章节我们实现了 ref 及其它配套的isRef、unRef 和 proxyRefs API。这一章开始实现computed计算属性。 认识computed 接受一个 getter 函数,返回一个只读的响应式 ref 对象。该 ref 通过 .value 暴露 getter 函数的返回值。…...
Java基础之注解
3.注解 3.1概述【理解】 概述 对我们的程序进行标注和解释 注解和注释的区别 注释: 给程序员看的注解: 给编译器看的 使用注解进行配置配置的优势 代码更加简洁,方便 3.2自定义注解【理解】 格式 public interface 注解名称 { public 属性类型 属性名() default 默认值…...
三、线性表
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 前言 提示:这里可以添加本文要记录的大概内容: 自学JAVA数据结构笔记,跟学视频为:黑马程序员Java数据结构与java算法全套教程…...
C++统计方形
统计方形 内存限制:256 MB 时间限制:1 S 题目描述 有一个n*m方格的棋盘,求其方格包含多少正方形、长方形(此处长方形不包含正方形) 输入格式 输入存在多组测试数据。每组测试数据输入两个整数n,m,数字不超…...
Tina_Linux配网开发指南
OpenRemoved_Tina_Linux_配网_开发指南 1 概述 1.1 编写目的 介绍Allwinner 平台上基于wifimanager-v2.0 的WiFi 配网方式,包括softap(WiFi ap 模式热点配网),soundwave(声波配网),BLE(蓝牙低功耗配网)。 1.2 适用范围 • allwinner 软件平台tina v5.0 版本及以…...
高频面试题|RabbitMQ如何防止消息的重复消费?
一. 前言最近有很多小伙伴开始找工作,在面试时,面试官经常会问我们这样一个题目:RabbitMQ如何防止重复消费?有很多小伙伴这个时候都在想,消息怎么还会重复消费呢???.......所以他们在面试后就跑来问壹哥,针对这个比…...
黑盒测试用例设计方法-边界值分析法
目录 一、边界值定义 二、边界值的考虑 三、边界值的优化 四、边界值的设计用例的步骤 五、案例 六、边界值的类型 一、边界值定义 边界值分析法就是对输入或输出的边界值进行测试的一种黑盒测试方法。通常边界值分析法是作为对等价类划分法的补充,这种情况下…...
项目风险管理中不可忽视的5个关键点
1、风险意识非常重要 项目经理必须要有风险意识,并不是项目计划做好就万事大吉,而是需要对项目风险进行预判,时刻保持风险意识,及时发现和处理项目风险。 项目风险管理关键:风险意识 2、建立组织风险资产库 寻…...
Linux->进程地址空间
目录 前言: 1. 程序地址空间回顾 2. 进程空间是什么 3. 进程地址空间与内存 4. 进程地址空间和内存的关联 5. 为什么要有进程地址空间 前言: 我们在平时学习的过程当中总是听到栈、堆、代码段等等储存空间,但是这些东西到底是什么&…...
【奶奶看了也不会】AI绘画 Mac安装stable-diffusion-webui绘制AI妹子保姆级教程
1.作品图 2.准备工作 目前网上能搜到的stable-diffusion-webui的安装教程都是Window和Mac M1芯片的,而对于因特尔芯片的文章少之又少,这就导致我们还在用老Intel 芯片的Mac本,看着别人生成美女图片只能眼馋。所以小卷这周末折腾了一天&#…...
基于stm32电梯管理系统设计
基于stm32电梯管理系统设计这里记录一下以前自己做的嵌入式课程设计,报告中的图片和文字太多了,全部一个一个把搬过来太麻烦了,需要完整文本和代码自行q我963160156,也可在微信公众号 *高级嵌入式软件* 里回复 *电梯* 查看完整版文章摘要关键…...
Spring中的FactoryBean 和 BeanFactory、BeanPostProcessor 和BeanFactoryPostProcessor解析
文章目录FactoryBean 和 BeanFactory后置处理器BeanPostProcessor 和 BeanFactoryPostProcessorBeanPostProcessorBeanFactoryPostProcessorFactoryBean 和 BeanFactory BeanFactory接⼝是容器的顶级接⼝,定义了容器的⼀些基础⾏为,负责⽣产和管理Bean的…...
【C++从入门到放弃】类和对象(上)
🧑💻作者: 情话0.0 📝专栏:《C从入门到放弃》 👦个人简介:一名双非编程菜鸟,在这里分享自己的编程学习笔记,欢迎大家的指正与点赞,谢谢! 类和对…...
什么牌子的蓝牙耳机便宜好用?四款高品质蓝牙耳机推荐
随着时代的发展,蓝牙耳机的使用频率越来越高,不少人外出时除了带手机外,蓝牙耳机也成为了外出必备的数码产品之一。现在的蓝牙耳机品牌众多,什么牌子的蓝牙耳机便宜好用?下面,我来给大家推荐四款高品质的蓝…...
eddsa 算法
信息安全课程设计:eddsa 算法 一、项目要求 使用 C 语言开发;可以实现公私钥生成、签名、认证;只需要手动输入明文,代码会自动生成公私钥、签名、认证;记录公私钥生成、签名、认证的时间;在 VS 上运行&am…...
Xcode Developer Document 开发者文档
总目录 iOS开发笔记目录 从一无所知到入门 文章目录IntroDeveloper Documentation 打开方式菜单栏点击 | 快捷键方式另一种打开方式Intro 2016年我在学校学Java的时候,要查某个Java类/方法的用法还得自己手动下载一种.chm格式的开发文档文件,…...
IntelliJ插件开发教程之新建项目
JetBrains公司系列产品IDEA、WebStrom、PyCharm、CLion、GoLand等都是基于IntelliJ Platform开发而成,掌握IntelliJ插件开发技能便能拥有提升开发效率的终极武器。本教程Demo源码请微信公众号“开发效率”进行获取。阅读原文如果您是JetBrains产品的用户,…...
解决SpringBoot中@RequestBody不能和Multipart同时传递的问题
问题描述 今天在做文件上传的时候,遇到了这么一个错误日志: Resolved[org.springframework.web.HttpMediaTypeNotSupportedException: Content type ‘multipart/form-data;boundary--------------------------771899451541318130280588;charsetUTF-8’…...
【华为OD机试模拟题】用 C++ 实现 - 统计匹配的二元组个数(2023.Q1)
最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 去重求和(2023.Q1) 文章目录 最近更新的博客使用说明统计匹配的二元组个数题目输入输出描述示例一输入输出说明示例二输入输出说明备注Code使用说明 参加华为od机试,一定要注意不要完全背诵代码&...
Vuex 面试题总结 的历史汇总!
一.vuex是什么?怎么使用?哪种功能场景使用它? Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。简单来说就是:应用…...
Redis缓存更新策略与缓存穿透、雪崩等问题的解决
文章目录一、缓存更新策略1、三种策略2、策略选择3、主动更新的方案二、缓存存在的问题1、缓存穿透2、缓存雪崩3、缓存击穿三、解决缓存问题1、自定义分布式锁2、解决缓存穿透问题3、解决缓存击穿问题一、缓存更新策略 1、三种策略 内存淘汰:redis自带的内存淘汰机…...
OSI和TCP/IP网络模型细讲
文章目录一、OSI七层参考模型二、TCP/IP体系结构三、TCP/IP参考模型四、沙漏计时器形状的TCP/IP协议族五、两种国际标准对比相似之处不同之处一、OSI七层参考模型 OSI参考模型共分为7层,低三层面向通信,可用软硬件实现;高三层面向信息处理&am…...
【正点原子FPGA连载】第十九章FreeRtos Hello World实验 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南
1)实验平台:正点原子MPSoC开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id692450874670 3)全套实验源码手册视频下载地址: http://www.openedv.com/thread-340252-1-1.html 第十九章FreeRto…...
php mysql高校田径运动会成绩管理系统
第一章 引言 1 1.1 选题背景 1 1.2 编写目的 2 1.3 目标 2 1.4 功能需求 3 第二章 开发工具介绍 4 2.1 PHP 4 2.2 APACHE 5 2.3 MYSQL数据库 5 2.4 运行环境 WINDOWS XP 6 2.5 XAMPP 6 2.6 DREAMWEAVE8 6 2.7 EDITPLUS 7 第三章 需求…...
吴中公司网站建设找哪家/各大免费推广网站
3.9 闲聊数据类型 字符串: 单引号 双引号 三引号 数值: 整数 浮点 布尔 复数类型3.9.1 整型(整数) Python3的整型和长整型无缝结合 不再区分 长度取决于内存 优点-利于大数计算3.9.2 浮点型(小数) 科学记数法 E记法 也可以是e 源码…...
泰安千橙网络/上海排名优化seo
一、PageRank的概念 PageRank,网页排名, 是一种由根据网页之间相互的超链接计算的技术,而作为网页排名的要素之一, 它由Larry Page 和 Sergey Brin在20世纪90年代后期发明,并以拉里佩吉(Larry Page…...
在制作网站前 不需要急于做的工作是/优化网站广告优化
我们知道,很多程序都直接文件拖放。例如常见的Excel,Word等等。如果要为我们自己的应用程序添加文件拖放到支持,那么可以按照如下的一些步骤完成 1. 设置窗体的allowdrop属性为true 2. 编写两个事件:DragEnter和DragDrop 以下是我…...
wordpress 文章索引/无锡seo公司
这是一个允许您流式传输子流程输出的解决方案。事后使用相同的模板静态加载它(假设您的子进程将其自己的输出记录到文件中;如果没有,则将进程输出记录到日志文件中留给读者练习)from flask import Response, escapefrom yourapp import appfrom subprocess import P…...
cms模板/百度app优化
按变量的生存周期来划分,Linux变量可分为两类,它们的修改方法如下:(1)永久的:需要修改配置文件,变量永久生效。 常见的配置文件包括: (1-1)/etc/profil…...
wordpress 缩略图地址/seo排名点击器原理
作者: 中国科学院大气物理研究所 律成林 ————————————————2023年1月26日追加内容———————————————— 使用m_vec时的注意事项: 在使用m_vec函数时,输入数据要用双精度数组(double)。如果是单精度数组(sing…...