新的垃圾:手撕 vector
起因:口出狂言 vector
实现起来“十分简单”
#pragma once
#include <cstddef>
#include <memory>
#include <type_traits>
#include <utility>
#include "test.h"
// 拷贝构造
template <typename T>
typename std::enable_if< !std::is_move_constructible<T>::value && !std::is_trivially_copyable<T>::value >::type
vector_data_move(T *begin, T *end, T *dest)
{
for(; begin != end; ++dest, ++begin)
{
fdbg("move(copy construct) (%p) -> (%p) count: %zu", begin, dest, end - begin);
::new (dest) T(*begin); // 只进行构造
begin->~T(); // 析构原有对象
}
}
// 移动构造
template <typename T>
typename std::enable_if< std::is_move_constructible<T>::value && !std::is_trivially_copyable<T>::type >::type // int 这个逼既能移动构造又能平凡复制
vector_data_move(T *begin, T *end, T *dest)
{
for(; begin != end; ++dest, ++begin)
{
fdbg("move(move construct) (%p) -> (%p) count: %zu", begin, dest, end - begin);
::new (dest) T(std::move(*begin)); // 移动构造 源对象就不用管了(释放内存或者被赋值覆盖)
}
}
// 平凡可复制
template <typename T>
typename std::enable_if< std::is_trivially_copyable<T>::value >::type
vector_data_move(T *begin, T *end, T *dest)
{
size_t count = end - begin;
fdbg("move(trivially_copy) (%p) -> (%p) count: %zu size: %zu", begin, dest, count, sizeof(T));
::memcpy(dest, begin, count * sizeof(T)); // 平凡可复制就是指像 C 结构体一样可以直接拷贝内存的对象
}
template <typename T>
class vector
{
public:
typedef T value_type; // 成员类型
typedef T & reference_type; // 引用
typedef const T & const_reference_type; // 以常量方式引用
typedef T * iterator_type; // 指针
typedef const T * const_iterator_type; // 以常量方式指针
typedef std::allocator<T> allocator_type; // 内存分配器
public:
// 默认构造
vector():
_data(nullptr),
_end(nullptr),
_capacity(nullptr)
{}
// 析构
~vector()
{
if (_data) // 考虑一下空容器的情况
{
_allocator.deallocate(_data, capacity());
fdbg("deallocate: at %p size %zu", _data, capacity());
}
}
// 访问
// 容器尺寸
size_t size() const { return _end - _data; }
size_t capacity() const { return _capacity - _data; }
// 迭代器
iterator_type begin() const { return _data; }
iterator_type end() const { return _end; }
const_iterator_type cbegin() const { return _data; }
const_iterator_type cend() const { return _end; }
// 容器修改
// 尾部插入
void push_back(const_reference_type val)
{
if (_end == _capacity)
{
// 烦的不行的重新分配和容器移动
return push_back_slow_path(val);
}
// 构造新对象
::new (_end++) value_type(val);
}
private:
// 扩容
void push_back_slow_path(const_reference_type val)
{
// 旧值
size_t oldsize = size();
size_t oldcap = capacity();
// 新值
size_t newcap = calculate_expand_size(oldsize);
// 申请新内存
iterator_type newdata = _allocator.allocate(newcap);
fdbg("allocate: at %p size %zu", newdata, newcap);
if (_data)
{
// 移动容器
fdbg("container will move: %p -> %p count: %zu", _data, newdata, _end - _data);
// 对象移动
vector_data_move<value_type>(_data, _end, newdata);
// 释放内存
_allocator.deallocate(_data, oldcap);
fdbg("deallocate: at %p size %zu", _data, oldcap);
}
// 实装新内存
_data = newdata;
_end = _data + oldsize;
_capacity = _data + newcap;
// 构造新对象
::new (_end++) value_type(val);
fdbg("moved size: %zu, capacity: %zu", size(), capacity());
}
// 计算新大小
size_t calculate_expand_size(size_t size)
{
// +1 是为了 size=0 的情况
if (size < static_cast<size_t>(512))
{
// 2 倍扩容
return size * 2 + 1;
}
else
{
// 25% 扩容
return size + static_cast<size_t>(size * 0.25) + 1;
}
}
private:
// 成员变量
iterator_type _data; // 首元素指针
iterator_type _end; // 逻辑尾后
iterator_type _capacity; // 容器尾后
allocator_type _allocator;
/*
* |++++++++++++++++++++++++++++++|---------------|
* ^ ^ ^
* |begin |end |capacity
*
* 注意是刚好错开的,因为 end, capacity 刚好是最后一个元素/“元素”的后一个元素,仅作比较参考
*/
};
test.h
#pragma once
#include <cstdio>
#include <stdio.h>
#include <stdarg.h>
// 没事往头文件定义普通函数就是作死
// 链接器报错多重定义警告
inline int test_title(const char *str)
{
return printf("[ %s ]===============\n", str);
}
inline int fdbg_impl(const char *funcname, const char *const fmt, ...)
{
int result = 0;
va_list args;
va_start(args, fmt);
result += printf("[ %s ]: ", funcname);
result += vfprintf(stdout, fmt, args);
result += printf("\n");
va_end(args);
return result;
}
#ifndef NDEBUG
#define fdbg(fmt, ...) do{ fdbg_impl(__func__, fmt, __VA_ARGS__); }while(0)
#else
#define fdbg(fmt, ...)
#endif
兄弟们,js 库函数怎么做啊,下面那些不会拆
(function(){
/** @type {HTMLCanvasElement} */
var canvas = document.getElementById("canvas");
/** @type {CanvasRenderingContext2D } */
var ctx = canvas.getContext("2d");
var mousepos = { x: 0, y: 0 }
window.addEventListener("mousemove", function(e){
mousepos.x = e.clientX
mousepos.y = e.clientY
})
function canvas_resize()
{
canvas.width = document.documentElement.clientWidth;
canvas.height = document.documentElement.clientHeight;
}
// canvas_resize();
window.addEventListener("resize", canvas_resize);
window.dispatchEvent(new Event("resize"));
// draw with ctx
function dwctx(func)
{
ctx.save()
func()
ctx.restore()
}
function hline(y)
{
// https://blog.csdn.net/weixin_38763607/article/details/114702929
dwctx(()=>{
ctx.beginPath()
ctx.moveTo(0, y)
ctx.lineTo(canvas.width, y)
ctx.lineWidth = 1
ctx.strokeStyle = '#000'
ctx.stroke()
ctx.fillText(y.toString(), 0, y - 2)
})
}
function vline(x)
{
dwctx(()=>{
ctx.beginPath()
ctx.moveTo(x, 0)
ctx.lineTo(x, canvas.height)
ctx.lineWidth = 1
ctx.strokeStyle = '#000'
ctx.stroke()
ctx.fillText(x.toString(), x, 0 + 10)
})
}
function pointpos(x, y)
{
vline(x)
hline(y)
}
function draw()
{
// clear
dwctx(()=>{
ctx.clearRect(0, 0, canvas.width, canvas.height)
})
dwctx(()=>{
ctx.fillText((new Date()).toLocaleTimeString(), 10, 10)
})
pointpos(mousepos.x, mousepos.y)
// ---
requestAnimationFrame(draw);
}
draw()
})()
让学校把我安排的明明白白
群里通知的只有两件事:
1. 8月28日返校,8月29日早上10点开会,签到,必须到
2. 可以自主实习,然而需要申请,15%的比例,而且必须实习单位录用转正而且要在一个月内签三方协议(而且还有个坑)
---
定义:定制班,就是跟学校有合作,上学期来学校开宣讲会的单位
如果没找到实习,请滚回学校参加学校安排实习
如果找到实习,但是单位不要你,请滚回学校参加安排
如果你找到了实习,且单位要你,请在学校安排实习结束后,滚回来上课(我:???)而且是我们这一届加的“新技术讲座”和“综合实践”(听说就是上学期的培训性质的“课”)
定制班不用走自主实习流程,而且课都不用上,连毕业设计都是安排上的,就是单位你喜不喜欢就不知道了
蕨了,山上的笋都让你给夺完了
有被 nuxt 的静态资源坑到
今晚一堆提交都只考虑了 github pages 上能用,然而本地开发就爆炸了(估计)
https://sinsong.github.io/microblog/
莉特雅 literal
写代码业余爱好者 amateur coder