自己实现一个智能指针
- 需要注意各种构造函数和assign操作符的重载,包括左值右值情况都要考虑
- 注意delete,防止内存泄漏
ini
复制代码
template <class T>
class SmartPtr {
public:
SmartPtr(T* p = nullptr) {
p_ = p;
if (p_ != nullptr) {
count_ = new int(1);
}
}
~SmartPtr() {
if (count_ != nullptr) {
(*count_)--;
if (*count_ == 0) {
if (p_ != nullptr) {
delete p_;
}
delete count_;
}
}
}
SmartPtr(const SmartPtr& oth) {
p_ = oth.p_;
count_ = oth.count_;
if(p_ != nullptr) {
*count_++;
}
}
SmartPtr(SmartPtr&& oth) {
p_ = oth.p_;
count_ = oth.count_;
oth.p_ = nullptr;
oth.count_ = nullptr;
}
SmartPtr& operator =(const SmartPtr& oth) {
if (this == &oth) {
return *this;
}
if (count_ !=nullptr && *count_ == 1) {
if (p_ != nullptr) {
delete p_;
}
delete count_;
}
p_ = oth.p_;
count_ = oth.count_;
(*count_)++;
return *this;
}
SmartPtr& operator = (SmartPtr&& oth) {
std::swap(p_, oth.p_);
std::swap(count_, oth.count_);
return *this;
}
T* operator ->() const {
return p_;
}
T& operator *() const {
return *p_;
}
//k
T& operator [](int index) {
return p_[index];
}
T* get() {
return p_;
}
int use_count() {
return count_ == nullptr? 0: *count_;
}
private:
T* p_ = nullptr;
int* count_ = nullptr;
};
struct ListNode {
int data;
SmartPtr<ListNode> prev;
SmartPtr<ListNode> next;
~ListNode(){ cout << "~ListNode()" << endl; }
};
int main(int argc, char **argv) {
SmartPtr<ListNode> node1(new ListNode);
SmartPtr<ListNode> node2(new ListNode);
cout << node1.use_count() << endl;
cout << node2.use_count() << endl;
node1->next = node2;
node2->prev = node1;
cout << node1.use_count() << endl;
cout << node2.use_count() << endl;
return 0;
}
自己实现一个queue
ini
复制代码
template <class T>
class SmartQueue {
public:
struct Node {
Node() = default;
Node(const T& t) {
val = t;
}
T val;
Node* pre = nullptr;
Node* next = nullptr;
};
SmartQueue() {
dummy_head_ = new Node();
dummy_tail_ = new Node();
dummy_head_->next = dummy_tail_;
dummy_tail_->pre = dummy_head_;
}
~SmartQueue() {
Release();
}
SmartQueue(const SmartQueue& oth) {
dummy_head_ = new Node();
Node* cur = dummy_head_;
Node* p_oth = oth.dummy_head_->next;
while (p_oth != nullptr) {
cur->next = new Node(p_oth->val);
cur->next->pre = cur;
cur = cur->next;
p_oth = p_oth->next;
}
dummy_tail_ = cur;
}
SmartQueue(SmartQueue&& oth) {
dummy_head_ = oth.dummy_head_;
dummy_tail_ = oth.dummy_tail_;
size_ = oth->size_;
oth->dummy_head_ = nullptr;
oth->dummy_tail_ = nullptr;
oth->size_ = 0;
}
SmartQueue& operator =(const SmartQueue& oth) {
if (this == &oth) {
return *this;
}
Release();
dummy_head_ = new Node();
Node* cur = dummy_head_;
const Node* p_oth = oth.dummy_head_->next;
while (p_oth != nullptr) {
cur->next = new Node(p_oth->val);
cur->next->pre = cur;
cur = cur->next;
p_oth = p_oth->next;
}
dummy_tail_ = cur;
}
void Release() {
Node* cur = dummy_head_->next;
while (cur != nullptr) {
delete cur->pre;
cur = cur->next;
}
delete dummy_tail_;
dummy_tail_ = nullptr;
dummy_head_ = nullptr;
size_ = 0;
}
T back() {
return dummy_tail_->pre->val;
}
T front() {
return dummy_head_->next->val;
}
void push_back(const T& t) {
auto pre = dummy_tail_->pre;
Node* new_node = new Node(t);
pre->next = new_node;
new_node->pre = pre;
new_node->next = dummy_tail_;
dummy_tail_->pre = new_node;
++size_;
}
void push_front(const T& t) {
auto next = dummy_head_->next;
Node* new_node = new Node(t);
dummy_head_->next = new_node;
new_node->next = next;
new_node->pre = dummy_head_;
next->pre = new_node;
++size_;
}
bool pop_back() {
if (dummy_head_->next == dummy_tail_) {
return false;
}
Node* n = dummy_tail_->pre;
n->pre->next = n->next;
n->next->pre = n->pre;
delete n;
--size_;
return true;
}
bool pop_front() {
if (dummy_head_->next == dummy_tail_) {
return false;
}
Node* n = dummy_head_->next;
n->pre->next = n->next;
n->next->pre = n->pre;
delete n;
--size_;
return true;
}
size_t size() const {
return size_;
}
void Debug() {
Node* p = dummy_head_->next;
while (p != dummy_tail_) {
cout << p->val << "->";
p = p->next;
}
cout << endl;
}
private:
size_t size_ = 0;
Node* dummy_head_ = nullptr;
Node* dummy_tail_ = nullptr;
};
实现memcpy和memmove
ini
复制代码
void* memcpy (void* dst, const void* src, size_t size) {
void* ret = dst;
while (size--) {
*(char*)dst = *(char*)src;
dst = (char*)dst + 1;
src = (char*)src + 1;
}
return ret;
}
void* memmove(void* dst, const void* src, size_t size) {
void* ret = dst;
// 没有重叠
if (dst <= src || (char*)dst >= (char*)src + size) {
while(size-- > 0) {
*(char*)dst = *(char*)src;
dst = (char*)dst + 1;
src = (char*)src + 1;
}
}
else {
dst = (char*)dst + size - 1;
src = (char*)src + size - 1;
while (size-- > 0) {
*(char*)dst = *(char*)src;
dst = (char*)dst - 1;
src = (char*)src - 1;
}
}
return ret;
}
自己实现一个hashmap
c
复制代码
#include <iostream>
// 使用了vector和list的模板库,实际上list可以自己实现,vector不是很有必要自己实现
// C++的哈希表是unordered_map,属于标准库,实现了各种高阶功能,建议研究一下源码
#include <vector>
#include <list>
const int MAX_SIZE = 10;
// 1. 首先定义一个键值对的数据结构
template<typename K, typename V>
struct KVNode {
K key;
V value;
KVNode(K k, V v) : key(k), value(v) {}
};
// 2. 自定义HashMap类
template<typename K, typename V>
class HashMap {
private:
// 2.1 通过一个简单的复合数据结构直接就可以实现HashMap,甚至有分桶。其中list也可以自己实现
std::vector<std::list<KVNode<K, V>>> table;
// 2.2 哈希函数,将键映射到索引
int hash(K key) {
return key % MAX_SIZE;
}
// 3. 实现初始化和增删查的方法
public:
// 3.1 初始化
HashMap() {
table.resize(MAX_SIZE);
}
// 3.2 增
void insert(K key, V value) {
int index = hash(key);
// 遍历当前链表,看是否已经存在
for (auto& kv : table[index]) {
if (kv.key == key) {
// 如果键已存在,更新值
kv.value = value;
return;
}
}
// 如果键不存在,插入新的键值对
table[index].emplace_back(key, value);
}
// 3.3 查
V get(K key) {
int index = hash(key);
for (auto& kv : table[index]) {
if (kv.key == key) {
return kv.value;
}
}
return -1; // 如果键不存在,返回-1或其他合适的值
}
// 3.4 删
void remove(K key) {
int index = hash(key);
table[index].remove_if([key](const KVNode<K, V>& kv) {
return kv.key == key;
});
}
};
// 测试
int main() {
HashMap<char, char> map;
map.insert(1, 42);
map.insert(2, 53);
std::cout << "Key 1: " << map.get(1) << std::endl;
std::cout << "Key 2: " << map.get(2) << std::endl;
map.remove(1);
std::cout << "After Delete: " << map.get(1) << std::endl; // 输出 -1
return 0;
}
自己实现一个timer
要点就是一个优先队列,每次epoll wait栈顶最早超时的时间
arduino
复制代码
#include <functional>
#include <iostream>
#include <algorithm>
#include <sys/epoll.h>
#include <sys/time.h>
#include <unistd.h>
#include <queue>
#include <vector>
class Timer
{
public:
Timer(unsigned long long expire, std::function<void(void)> fun)
: expire_(expire), fun(fun)
{
}
inline void run() { fun(); }
inline unsigned long long getExpire() const{ return expire_; }
private:
std::function<void(void)> fun;
unsigned long long expire_;
};
class TimerManager
{
public:
TimerManager() {}
Timer *addTimer(int timeout_ms, std::function<void(void)> fun)
{
if (timeout_ms <= 0) {
return NULL;
}
unsigned long long now = getCurrentMillisecs();
Timer* timer = new Timer( now+timeout_ms, fun);
queue_.push(timer);
return timer;
}
void delTimer(Timer* timer)
{
std::priority_queue<Timer*,std::vector<Timer*>,cmp> newqueue;
while( !queue_.empty() )
{
Timer* top = queue_.top();
queue_.pop();
if( top != timer )
newqueue.push(top);
}
queue_ = newqueue;
}
unsigned long long getRecentTimeout()
{
unsigned long long timeout = -1;
if( queue_.empty() )
return timeout;
unsigned long long now = getCurrentMillisecs();
timeout = queue_.top()->getExpire() > now? queue_.top()->getExpire() - now:0;
return timeout;
}
void takeAllTimeout()
{
unsigned long long now = getCurrentMillisecs();
while ( !queue_.empty() )
{
Timer* timer = queue_.top();
if ( timer->getExpire() <= now ) {
queue_.pop();
timer->run();
delete timer;
continue;
}
return;
}
}
unsigned long long getCurrentMillisecs()
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
return ts.tv_sec * 1000 + ts.tv_nsec / (1000 * 1000);
}
private:
struct cmp
{
bool operator()(Timer*& lhs, Timer*& rhs) const { return lhs->getExpire() > rhs->getExpire(); }
};
std::priority_queue<Timer*,std::vector<Timer*>,cmp> queue_;
};
int main () {
TimerManager tm;
int epfd = epoll_create(1);
// epoll_ctl(epfd, ...); //将所有需要监听的socket添加到epfd中
epoll_event events[1];
tm.addTimer(1000, []() { std::cout << "hello world" << std::endl; });
while (1) {
int n = epoll_wait(epfd, events, 1, tm.getRecentTimeout());
tm.takeAllTimeout();
}
return 0;
}
float转string
c
复制代码
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
using namespace std;
std::string i2s(int i, int times)
{
if (i == 0)
{
return "0";
}
std::vector<int> v;
v.reserve(16);
while (i > 0)
{
v.push_back(i % 10);
i /= 10;
--times;
}
while (times > 0) {
v.push_back(0);
--times;
}
std::stringstream ss;
for (int j = v.size() - 1; j >= 0; --j)
{
--times;
ss << v[j];
}
return ss.str();
}
std::string float2str(float f)
{
std::stringstream result;
// 符号
if (f < 0)
{
result << "-";
f = -f;
}
// 整数部分
int z = int(f);
result << i2s(z, 0);
// 小数部分
float x = f - float(z);
if (x < 1e-6)
{
return result.str();
}
int times = 0;
while (x - int(x) > 1e-6) // 判断有几位小数,但是*10后可能丢失精度
{
x *= 10;
++times;
}
// 小数点
result << "." << i2s(int(x), times);
return result.str();
}
int main()
{
cout << float2str(2.5) << endl;
cout << float2str(10.5) << endl;
cout << float2str(0.55002564565555) << endl;
return 0;
}
无锁链表与CAS
compare_exchange_weak 方法用于将原子对象的当前值与期望值进行比较,如果相等,则将其更新为新值。如果不相等,则将原子对象的当前值加载到期望值中,并返回 false。
markdown
复制代码
bool compare_exchange_weak(T& expected, T desired, std::memory_order success, std::memory_order failure) noexcept;
bool compare_exchange_weak(T& expected, T desired) noexcept; // 简化版本
- `expected`: 期望值,如果原子对象的当前值与此值相等,则更新为 `desired`。
- `desired`: 用于更新原子对象的值。
- `success`: 成功时的内存序。
- `failure`: 失败时的内存序。
arduino
复制代码
template<typename T>
class LockFreeStack {
private:
std::atomic<Node<T>*> head;
public:
LockFreeStack() : head(nullptr) {}
void push(T value) {
Node<T>* newNode = new Node<T>(value);
newNode->next = head.load(std::memory_order_relaxed);
while (!head.compare_exchange_weak(newNode->next, newNode,
std::memory_order_release,
std::memory_order_relaxed)) {
// CAS failed, newNode->next is updated with the new head value
}
}
bool pop(T& result) {
Node<T>* oldHead = head.load(std::memory_order_relaxed);
while (oldHead != nullptr &&
!head.compare_exchange_weak(oldHead, oldHead->next,
std::memory_order_acquire,
std::memory_order_relaxed)) {
// CAS failed, oldHead is updated with the new head value
}
if (oldHead == nullptr) {
return false; // Stack is empty
}
result = oldHead->data;
delete oldHead;
return true;
}
};
priorty queue 使用
c
复制代码
// 自定义比较器
struct Compare {
bool operator()(const std::pair<int, int>& a, const std::pair<int, int>& b) {
// 根据第二个元素进行比较,构造大顶堆
return a.second < b.second;
}
};
int main() {
// 声明一个 std::priority_queue,使用自定义比较器
std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int>>, Compare> pq;
// 插入一些元素
pq.push({1, 20});
pq.push({2, 15});
pq.push({3, 30});
pq.push({4, 10});
// 输出并移除队列中的元素
while (!pq.empty()) {
auto p = pq.top();
std::cout << "(" << p.first << ", " << p.second << ")" << std::endl;
pq.pop();
}
return 0;
}
std::function 使用
c
复制代码
#include <iostream>
#include <functional>
#include <vector>
using namespace std;
void callFunction(const std::function<void(int)>& func, int value) {
func(value);
}
void printValue(int x) {
std::cout << "Value: " << x << std::endl;
}
template <class T>
void Fun(std::vector<T>& vec, const std::function<void(T)>& func) {
for (auto t: vec) {
func(t);
}
}
int main() {
// 使用普通函数
// callFunction(printValue, 10);
// // 使用 lambda 表达式
// callFunction([](int x) { std::cout << "Lambda Value: " << x << std::endl; }, 20);
// // 使用 std::bind
// auto boundFunc = std::bind(printValue, std::placeholders::_1);
// callFunction(boundFunc, 30);
std::vector<int> v({1,2,3});
Fun<int>(v, [](int i) {cout <<i <<endl;});
return 0;
}
float 转 string
c
复制代码
#include <sstream>
#include <iostream>
#include <string>
#include <vector>
std::string i2s(int i, int min_lenth)
{
if (i == 0)
{
return "0";
}
std::vector<int> v;
v.reserve(16);
while (i > 0)
{
v.push_back(i % 10);
i /= 10;
--min_lenth;
}
std::stringstream ss;
for (int j = v.size() - 1; j >= 0; --j)
{
--min_lenth;
ss << v[j];
}
return ss.str();
}
std::string float2str(float f)
{
std::stringstream result;
if (f < 0)
{
result << "-";
f = -f;
}
int z = int(f);
float x = f - float(z);
result << i2s(z, 0);
if (x < 1e-6)
{
return result.str();
}
int min_lenth = 0;
while (x - int(x) > 1e-6)
{
x *= 10;
++min_lenth;
}
result << "." << i2s(int(x), min_lenth);
return result.str();
}
int main()
{
std::cout << float2str(0) << std::endl;
std::cout << float2str(-0.15) << std::endl;
std::cout << float2str(10) << std::endl;
std::cout << float2str(-100.586) << std::endl;
std::cout << float2str(2.5) << std::endl;
std::cout << float2str(10.5) << std::endl;
std::cout << float2str(0.55002564565555) << std::endl;
return 0;
}
URL
c
复制代码
#include <iostream>
#include <cctype>
#include <string>
#include <unordered_set>
using namespace std;
class IsServer {
public:
void Set(const std::string& url) {
black_list_.insert(FormatUrl(url));
}
bool IsBlackListed(const std::string& url) {
return black_list_.count(FormatUrl(url)) > 0;
}
std::string FormatUrl(const std::string& url) {
has_handle_port_ = false;
std::string res = "";
size_t p = RemoveProtocol(url);
while(p < url.size()) {
char c = url[p];
if (c == ':') {
IgnorePort(url, p, res);
}
else if (c == '?') {
return res;
}
else if (c == '/') {
if (res.back() =='/') {
++p;
continue;
}
else {
res.push_back(c);
}
}
else {
res.push_back(std::tolower(c));
}
++p;
}
if(res.back() == '/') {
res.pop_back();
}
return res;
}
private:
void IgnorePort(const std::string& url, size_t& i, std::string& res) {
if (has_handle_port_) {
res.push_back(url.at(i));
return;
}
while (i < url.size() && url.at(i) != '/') {
++i;
}
if (url.at(i) == '/' && res.back() != '/') {
res.push_back( url.at(i));
}
has_handle_port_ = true;
}
size_t RemoveProtocol(const std::string& url) {
size_t first_slash = url.find('/');
size_t pos = url.find("://");
if (pos == url.npos || pos > first_slash) {
return 0;
}
return pos + 3;
}
bool has_handle_port_ = false;
std::unordered_set<std::string> black_list_;
};
int main () {
IsServer is;
cout << is.FormatUrl("AKA.MS/A/b/C") << endl;
cout << is.FormatUrl("https://aks.ms/a/b/c") << endl;
cout << is.FormatUrl("http://aks.ms/a://b/c") << endl;
cout << is.FormatUrl("http://aks.ms/a://b/c") << endl;
cout << is.FormatUrl("aka.ms:80/a/b/c?p=1&q=2") << endl;
cout << is.FormatUrl("aks.ma/a///b////c") << endl;
cout << is.FormatUrl("aks.ma/a://b/c") << endl;
}
thread 生产消费者
#include <iostream>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <atomic>
class Worker {
public:
Worker() : stop_thread_(false) {
work_thread_ = std::thread(&Worker::WorkThread, this);
}
~Worker() {
{
std::unique_lock<std::mutex> lock(queue_mutex_);
stop_thread_ = true;
}
queue_cond_var_.notify_all();
if (work_thread_.joinable()) {
work_thread_.join();
}
}
void Enqueue(int item) {
{
std::unique_lock<std::mutex> lock(queue_mutex_);
work_queue_.push(item);
}
queue_cond_var_.notify_one();
}
private:
void WorkThread() {
while (true) {
int item;
{
std::unique_lock<std::mutex> lock(queue_mutex_);
queue_cond_var_.wait(lock, [this]() { return stop_thread_ || !work_queue_.empty(); });
if (stop_thread_ && work_queue_.empty()) {
return;
}
item = work_queue_.front();
work_queue_.pop();
}
ProcessItem(item);
}
}
void ProcessItem(int item) {
std::cout << "Processing item: " << item << std::endl;
// 这里可以添加实际的处理逻辑
}
std::thread work_thread_;
std::queue<int> work_queue_;
std::mutex queue_mutex_;
std::condition_variable queue_cond_var_;
std::atomic<bool> stop_thread_;
};
int main() {
Worker worker;
for (int i = 0; i < 10; ++i) {
worker.Enqueue(i);
}
// 给一点时间让工作线程处理队列中的元素
std::this_thread::sleep_for(std::chrono::seconds(2));
return 0;
}
异步线程池
#include <iostream>
#include <future>
#include <vector>
#include <functional>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
class ThreadPool {
public:
ThreadPool(size_t thread_num) {
for (size_t i = 0; i < thread_num; ++i) {
workers_.emplace_back([this] {
while (true) {
std::function<void()> task;
{
std::unique_lock<std::mutex> lock(queue_mutex_);
condition_.wait(lock, [this] { return stop_ || !task_queue_.empty(); });
if (stop_ && task_queue_.empty()) {
return;
}
task = std::move(task_queue_.front());
task_queue_.pop();
}
task();
}
});
}
}
template <class F, class... Args>
auto AddFuture(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type> {
using return_type = typename std::result_of<F(Args...)>::type;
auto task = std::make_shared<std::packaged_task<return_type()>>(std::bind(std::forward<F>(f), std::forward<Args>(args)...));
std::future<return_type> result = task->get_future();
{
std::unique_lock<std::mutex> lock(queue_mutex_);
if (stop_) {
throw std::runtime_error("enqueue on stopped ThreadPool");
}
task_queue_.emplace([task]() { (*task)(); });
}
condition_.notify_one();
return result;
}
template <class ItemType, tepename Function>
bool Visit(const int thread_num, const std::vector<ItemType>& container, Function&& visit_func, int timeout_ms = 0) {
if (thread_num == 0) {
return false;
}
int container_size = container.size();
int item_num_for_one_thread = std::ceil((double)container_size / thread_num);
std::vector<std::future<bool>> futures;
futures.resize(std::min(thread_num,container_size));
auto func_ptr = std::make_shared<Function>(std::move(visit_func));
for (int i = 0; i < futures.size(); ++i) {
const int start_index = i * item_num_for_one_thread;
if (start_index >= container_size) {
continue;
}
const int end_index = std::min((container_size - 1), start_index + item_num_for_one_thread - 1);
futures[i] = AddFuture([start_index, end_index, &container, func_ptr, this]() {
for (int j = start_index; j <= end_index; ++j) {
bool res = (*func_ptr)(container[j]);
}
return true;
});
}
if (timeout_ms == 0) {
for (int i = 0; i < futures.size(); ++i) {
futures[i].wait();
}
}
else {
for (int i = 0; i < futures.size(); ++i) {
auto status = futures[i].wait_for(std::chrono::milliseconds(timeout_ms));
if (status == std::future_status::timeout) {
LOG_ERROR("wait for future timeout");
}
}
}
return true;
}
template <class ContainerType, tepename
~ThreadPool() {
{
std::unique_lock<std::mutex> lock(queue_mutex_);
stop_ = true;
}
condition_.notify_all();
for (std::thread& worker : workers_) {
worker.join();
}
}
private:
std::vector<std::thread> workers_;
std::queue<std::function<void()>> task_queue_;
std::mutex queue_mutex_;
std::condition_variable condition_;
bool stop_ = false;
};
int main() {
const size_t thread_num = 4; // 限定线程数量为4
ThreadPool pool("pool", thread_num);
std::string s = "hello world";
auto sp = std::make_shared<std::string>("hello world");
pool.AddFuture([sp]() {
std::cout << *sp << std::endl;
return true;
});
// visit
// 并行将string从s_vec写到map里
std::vector<std::string> s_vec;
const int vec_size = 5000;
for (int i = 0; i < vec_size; ++i) {
s_vec.push_back(std::to_string(i));
}
std::mutex mu_;
std::map<int, std::string> map_;
auto func = [&mu_](const std::string& s) {
std::lock_guard<std::mutex> lock(mu_);
map_.emplace(stoi(s), s);
return true;
}
bool res = pool.Visit(10, s_vec, std::move(func));
for (const auto& [k, v]: map_) {
std::cout <<k << ":" << v << std::endl;
}
return 0;
}