C++
...
Muzzik
动动你的金手指点个赞吧!
展开
-
C++模板使用记录
设置默认模板参数template<class T, typename = typename **这里写模板参数限制**>void func(T a) { // ...}模板返回类型限制// 这里限制了只能T只能为int和bool两种类型template<class T, typename = typename std::enable_if<std::is_same<int, T>::value || std::is_same<bool, T&.原创 2020-07-13 01:46:54 · 190 阅读 · 0 评论 -
C++ 左右值参数兼容, 让你的函数变得更为易用
这里可以模拟STL中的实现,自己改良了一下,让其可以返回值。template<class T, class... Args>T _func(Args&&... args_) { T data(std::forward<Args>(args_)...); return static_cast<T>(data);}test& func(test& data_) { return _func<test&>(da原创 2020-07-12 20:17:41 · 364 阅读 · 0 评论 -
C++ 右值使用技巧
延长将亡生命周期第一种方法:test get_t() { return test();}int main() { test t = get_t();}调用顺序: 构造第二种方法:test get_t(test&& a) { return a;}int main() { test t = get_t(test());}调用顺序: 构造 -> 移动构造 -> 析构备注: 这里之所以不能避免移动构造和析构个人猜测是因为不知道接收.原创 2020-07-12 20:10:40 · 177 阅读 · 0 评论 -
应用程序没有调用 WSAStartup,或者 WSAStartup 失败。一次奇怪的错误
在release环境下,我的代码原本是这样:assert(WSAStartup(MAKEWORD(2, 2), &wsa) == 0);莫名其妙的出现的这个错误,结果我认真看了几次,发现vs直接跳过了这个函数的执行, 当时就傻眼了,知道release会优化,但是这样太变态了吧,assert断言内的函数语句不会执行。然后我改回了下面这样就好了int re = WSAStartup(MAKEWORD(2, 2), &wsa);if (re) { //错误处理}...原创 2020-06-07 11:06:29 · 5445 阅读 · 0 评论 -
最精简的sha1编码函数,还不快来试试?
······在网上很多sha1编码代码是臃肿且难以理解的。不过没关系,我的代码只有难以理解(滑稽)。创造期间参考了这位兄弟的代码,写的不错。······接下来大家可以试试我的代码。唯一的好处就是简洁,性能上还没和一般的对比过。大家可以试试:亮代码:void sha1(std::string& data_) { // 计算占用空间 uint32_t size, i, n; uint32_t len = static_cast<uint32_t>(data_.length());原创 2020-06-06 07:53:09 · 727 阅读 · 0 评论 -
C++ 死锁检测
······不想写注解了,认真点的人看代码和注释都能懂。第一版,还没优化性能。另外建议不要将死锁处理的代码镶入release版本之中,会影响性能。最好的办法是用来调试。在debug时先将出现死锁的地方排除。然后发布时去掉这个死锁检测系统,可以利用宏。······源码及使用代码都在下面了,命名和函数体都可以按照自己习惯进行重构。希望能帮到大家。如果觉得还行那就给个赞吧。struct test { CRITICAL_SECTION cri; test() { InitializeCriticalS原创 2020-06-02 21:04:47 · 2321 阅读 · 0 评论 -
C++ 一句代码打印当前线程ID
功能代码: printf("ThreadID: %d\n", (*(uint32_t*)&std::this_thread::get_id());我们要获取线程id,那么必然要用到get_id这个函数,那么我们看看这个函数返回的是什么。看到了吗, _Thrd_id()其实是一个uint32_t类型的返回值,但是却被转换成了thread::id类型,那么我们再来看看thread::i...原创 2020-04-02 03:06:38 · 12154 阅读 · 2 评论 -
关于AcceptEx函数
AcceptEx函数的第一个参数listen_socket和第二个参数accept_sock不能相同。并且第一个参数listen_socket必须开启监听,否则会返回10022错误。AcceptEx函数的缓冲区如果设为0字节,那么每次发到客户端将延迟10ms左右,底层原因。。如果收到连接请求,GetQueuedCompletionStatus函数的lpCompletionKey参数将是调用CreateIoCompletionPort绑定listen_socket到完成端口的第三个参数。...原创 2020-06-01 23:22:33 · 823 阅读 · 0 评论 -
C++判断是否为有效IP地址
std::string ip("199.199.199.199");std::regex check_ip("(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[1-9])[.](25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[1-9])[.](25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[1-9])[.](25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-原创 2020-06-01 06:06:28 · 1311 阅读 · 0 评论 -
C++ std::regex正则表达式
使用std::string str("123456");std::regex check("123");bool re1 = regex_match(str, check); //falsebool re2 = regex_search(str, check); //truestd::smatch result; //匹配结果if (regex_search(ip, result, check_ip))//这里用regex_match或者regex_search都可以{ fo.原创 2020-06-01 05:19:09 · 1576 阅读 · 0 评论 -
让VS的debug程序在其他电脑运行
······大家都知道,除非是安装了VS的电脑,不然在其他电脑上运行VS编译的debug程序就会显示运行时错误(0x0000…)这样的弹窗。其实这是因为没有debug的运行库导致的,那怎么查看运行时的dll呢。这也是我在调试程序时发现的。那就是利用dmp转储文件查看。······首先我们需要设置转储文件函数。这里请大家百度 C++生成dump文件。 然后在程序内手动抛出一个异常,使用throw即可。然后我们吧dmp文件拖到VS内,就会出现这个画面看到了吗?模块那里有我们运行时调用的所有dll。这下就简原创 2020-06-01 02:01:31 · 1949 阅读 · 1 评论 -
std::stringstream、std::istringstream、std::ostringstream有何意义?为何使用它们?
std::stringstream所能办到的事std::string也能办到,那它有何意义呢?······我在实际使用中发现,std::stringstream变量可以使用 << 输入数字类型。而std::string.append只能连接字符串。······所以用std::stringstream会更加便捷。std::stringstream的str()函数是返回的一个std::string临时变量,所以我们在使用过程中最好用一个std::string temp(std::stringst原创 2020-05-31 23:29:32 · 714 阅读 · 0 评论 -
C++线程安全的定时器(时间堆)实现
自己写的一个时间堆,望大佬指出不足之处。time_heap.h#pragma once#include <Windows.h>#include <future>static uint32_t max_size = 64; //最大储存数class time_heap {private: struct event { friend class time_...原创 2020-03-21 19:20:05 · 2132 阅读 · 2 评论 -
如何保证在多线程中对象的有效性?进来告诉你
大家一定在网上看过其他文章,都是说用std::shared_ptr,其实还有一种情况,就是在std::shared_ptr也销毁后的情况下调用对象的函数,这时候会直接抛出错误那么我们如何安全的使用一个对象呢,很简单,利用std::shared_ptr + std::enable_shared_from_this,如果我们在对象销毁后再调用对象成员函数 std::shared_from_this() 获取指针的时候就会抛出异常。起初觉得并没有什么用,用this访问其他成员也会报错啊。但是我转念一想,抛出异常原创 2020-05-30 00:40:34 · 241 阅读 · 0 评论 -
std::enable_shared_from_this有什么意义?进来告诉你
之前我一直不知道std::enable_shared_from_this有什么意义,官方的解答是传递自身的智能指针,但我也一直没用到,都是以第三者的身份管理和传递其他类型的智能但是,直到我看到了一篇知乎的帖子,上面是这么说的:需求: 在类的内部需要自身的shared_ptr 而不是this裸指针场景: 在类中发起一个异步操作, callback回来要保证发起操作的对象仍然有效.但是我自己测试了一下,对象销毁后再调用对象成员函数发现用std::enable_shared_from_this获取指针原创 2020-05-30 00:18:41 · 758 阅读 · 1 评论 -
C++利用模板推导数组长度
大家学会点个赞哦// 任意类型数组template <typename T, int N>int ArraySize1(T(&arr)[N]) { return N;}原创 2020-05-28 16:51:28 · 837 阅读 · 0 评论 -
std::shared_ptr的使用心得
如果要在一个lambda表达式中使用一个shared_ptr对象的话,不要使用 [&] () { 内部使用 } 这样的方式。因为捕获列表不会给shared_ptr增加引用数。就有可能导致我们使用的时候shared_ptr已经销毁了。正确的使用方式是 [] (std::shared_ptr& obj) { 内部使用 }, 然后再用std::bind函数绑定shared_ptr对象到lambda表达式 ,这样shared_ptr就会增加引用计数,我们之后使用也不会有问题了。...原创 2020-05-26 15:42:39 · 1119 阅读 · 0 评论 -
std::swap不是std的成员解决
其实swap的定义在utility头文件中,我们只需要 #include <utility> 就好了。原创 2020-05-25 23:02:05 · 1101 阅读 · 0 评论 -
C++用for遍历自定义类
正确的做法是像STL容器那样,创建一个迭代器类,然后里面重载 !=(比较), ++(递增),*(解引用) 这几个函数。例如:template <class T>class iterator {private: T* _data;protected:public: // 构造函数,传进迭代器管理的值 iterator(T* data_) : _data(data) {} bool operator !=(const iterator& that) { //原创 2020-05-24 22:26:35 · 2969 阅读 · 1 评论 -
C++ Sleep以及this_thread::sleep_for精度不够的问题
代码测试休眠5秒钟,一秒钟休眠一次测试,WaitForSingleObject函数的精度比sleep和sleep_for的精度提高10ms左右;WaitForSingleObject在等待的过程中会进入一个非常高效的沉睡等待状态,只占用极少的CPU时间片。使用代码:HANDLE eve = CreateEvent(NULL, FALSE, FALSE, NULL); while (WaitForSingleObject(eve, 超时时间(毫秒)) != WAIT_OBJECT..原创 2020-05-24 20:06:47 · 3751 阅读 · 0 评论 -
C++最大堆实现
max_heap.h#pragma once#include <cstdint>template <class T>class max_heap {private: struct node { uint32_t size; T* data; }; node* _heap; //最大堆 uint32_t _max_size; //最大存储数 uint32_t _size; //存储数 // 扩容 void expansion();原创 2020-05-24 01:37:11 · 380 阅读 · 0 评论 -
C++最小堆实现
mini_heap.h#pragma once#include <cstdint>template <class T>class mini_heap {private: struct node { uint32_t size; T* data; }; node* _heap; //最小堆 uint32_t _max_size; //最大存储数 uint32_t _size; //存储数 // 扩容 void expansion();原创 2020-05-24 01:35:47 · 446 阅读 · 0 评论 -
最小堆的指定删除
其实最小堆是可以指定删除某个节点的,包括最大堆。只要使用正确的方法伪代码:// 向下调整if (末尾节点key >要删除的节点key) { //这里就使用尾换头的方法调整,只不过把所谓的 "头" 换成了指定节点}// 向上调整else { //这里的逻辑比尾换头简单的多,也是我们删除指定节点重要的地方,向上调整 因为我们要删除的节点key >尾节点key,为了符合有序性的规则就必须将尾节点向上调整,调整方法也很简单:...原创 2020-05-23 23:51:58 · 1697 阅读 · 0 评论 -
C++基础数据类型最大值/最小值宏
包含#include <cstdint> 头文件后就能使用这些宏原创 2020-05-23 10:48:24 · 642 阅读 · 0 评论 -
关于inline的小知识
1. 要想实现inline函数必须将inline放在函数定义前,而不是函数声明前2. protected和public里的inline函数如果将定义放在了cpp文件中那么如果在其他源文件中使用此函数将会编译错误3. 最好将inline函数定义放在头文件中,某些inline private函数可以忽略...原创 2020-05-15 04:01:19 · 366 阅读 · 0 评论 -
Visual Studio 20xx 设置其他后缀的文件内语法提示
1. 打开VS, 点击右上角的齿轮按钮,点击选项进入选项后选择文件编辑器 -> 文件扩展名,添加扩展名即可效果图:原创 2020-05-15 23:21:32 · 211 阅读 · 0 评论 -
浅析std::string的append方法
string内部有多个append函数,我们就拿其中一个来说(基本原理都一样)。其中第一步中的if (_Count <= _Mypair._Myval2._Myres - _Old_size)可以翻译为如果(加入的字符大小<= 当前大小 - 已存在的字符占用大小) ,其内部直接就是将我们append的字符复制进的当前的数组内。第二步其实就很简单,重新创建一个满足需求大小的数组并将之前的数据和我们append添加的数据拷贝进去。那么创建的数组大小是多少呢,我们来看这个函数,这是第二部跳转原创 2020-05-15 05:09:53 · 5235 阅读 · 0 评论 -
C++ IOCP问题备注
【1236错误】情况如下: 1.client连接server 2.client发送消息到server 3.client使用closesocket(sock); 4.server接收到关闭socket消息(lpNumberOfBytesTransferred为0, 注意:如果客户端发送的是空消息同样为零)然后使用closesocket函数关闭了这个客户端的s...原创 2020-04-30 14:29:08 · 568 阅读 · 0 评论 -
减少锁竞争方法
1. 设置双重进入锁判断,例:bool enter = false;void test() { if (enter) { return; } mutex.lock(); if (enter) { return; } enter = true; mutex.unlock(); // 代码块.. enter = false;}第一次的判断可以防止在代码块执行的时间内其他线程频繁执行test函.原创 2020-05-11 02:55:58 · 298 阅读 · 0 评论 -
WSASend体会以及WSAENOBUFS错误思路
1. 无论投递多大的缓冲区它都是立即返回2. 返回成功只是表示将数据拷贝到了发送缓冲区3.GetQueuedCompletionStatus返回成功只表示发送成功,并不代表对方成功接收到数据4.WSAWaitForMultipleEvents 和 WSAGetOverlappedResult 同 3 类似个人结论:网上的宣称投递0字节WSASend并没有什么卵用。WSASend返回WSAENOBUFS不用理会,前提是你必须把发送缓冲列表里的数据放在GetQueuedCompletionStatu..原创 2020-05-10 05:27:58 · 750 阅读 · 0 评论 -
教你获取new出的数组大小
之前在网上没怎么看到获取数组大小的文章,现在给大家说一下自己的方法。首先,C++new出的数组或者对象C++都是知道其内存大小的,既占用字节,而这个占用字节在哪儿呢,没错,就在变量地址 - 4个int占用字节的大小 = 存放new对象的占用字节(仅在64位环境下测试,32位也可以试试)。那么知道这个就简单了。我们可以先获取到存放其占用字节的内存地址,内存地址 = (int*(对象指针)) -...原创 2020-05-07 18:15:16 · 4407 阅读 · 3 评论 -
C++线程安全的智能指针
smart_ptr.hpp#pragma once#include <cstdint>#include <memory>template <class T>class smart_ptr {private: T* _obj; uint32_t _count; void add(); void dec();protected:pub...原创 2020-05-04 05:31:35 · 848 阅读 · 0 评论 -
C++原子性加减(自增/自减)
long count = 0;_InterlockedIncrement(&count); //自增_InterlockedDecrement(&count); //自减宏#include <xatomic.h>_MT_INCR(count); //自增_MT_DECR(count); //自减可以直接使用xatomic头...原创 2020-05-04 05:09:02 · 1904 阅读 · 0 评论 -
Socket端口复用和非阻塞套接字
BOOL optval = TRUE;// 端口复用if (SOCKET_ERROR == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, sizeof(optval))) {}// 非阻塞套接字if (SOCKET_ERROR == ioctlsocket(sock, FIONBIO, (u_long ...原创 2020-05-03 05:19:21 · 163 阅读 · 0 评论 -
基础数据类型值传递、指针传递的取舍
传递基础数据类型的时候, 最重要的一点是看占用空间大小,如果是32位系统, 想要传递int, char, short这种类型的话使用值传递比较好,因为这些类型的占用空间 <= 指针占用空间(4字节),如果是long long类型的话则使用指针较好,因为long long的占用空间为8字节, >指针占用空间(4字节)。而在64位系统中,long long和指针占用空间都为8字节,传...原创 2020-04-30 14:22:19 · 155 阅读 · 0 评论