C++ 完美转发
1. 什么是完美转发?提到完美转发,就有必要先说一下,什么是转发,什么样的转发才称得上是完美转发。
在 C++ 中,转发指的就是函数之间的参数传递(例如函数 f1 接收了一个参数 a,而后又将此参数 a 传递给了其函数体内调用的另一个函数 f2)。
而完美转发指的就是在函数之间传递参数的过程中,参数在传递后的属性保持不变(如左值仍是左值,右值仍是右值,const 修饰也会保留)。
2. 常规转发存在的问题对于普通的转发,参数在函数间传递时属性可能会发生改变,我们看一个例子。
12345678910111213141516171819202122232425#include <iostream>#include <utility>void an_orther_fun(int a, int& b){ std::cout << "in an_orther_fun(): a = " << a << ", b = " << ++b << std::e ...
C++ std::move() 实现详解
本文不介绍 std::move() 的功能与用法,有了解需要可参考 std::move - cppreference.com。
本文主要研究 std::move() 的实现原理,从其定义出发,自顶向下剖析。
1. std::move() 的定义移动函数 std::move() 定义在头文件 <utility> 中。
下面的定义取自 GCC 源码:
123456789/** * @brief Convert a value to an rvalue. * @param __t A thing of arbitrary type. * @return The parameter cast to an rvalue-reference to allow moving it.*/template<typename _Tp> constexpr typename std::remove_reference<_Tp>::type&& move(_Tp&& __t) noexcept { return s ...
C++ 内存模型和原子操作
C++ 新标准引入了不少新特性,其中一项非常重要,它既不是新的语法功能,也不是新的程序库工具,而是新的线程感知的内存模型,却被大多数程序员所忽略。内存模型精确定义了基础构建单元应当如何运转。唯有以内存模型为基石,C++ 提供的并发工具方能可靠的工作。多数程序员之所以会忽略内存模型,是因为我们只需要借助互斥保护数据,并采用条件变量、future、线程闩或线程卡来触发事件信号,就足以将多线程运用自如,结果甚少有人深究底层细节。只有当我们尽力“贴近计算机底层硬件”,内存模型的精确细节的重要作用才会彰显。
不论其他语言如何定位,C++ 都是操作系统级别的编程语言。C++ 标准委员会的一个目标是领 C++ 尽量贴近计算机底层,而不必改用其他更低级的语言,C++ 十分灵活,可满足程序员的许多需求,包括容许他们在必要时“贴近计算机底层硬件”,语言本身不应构成障碍。原子类型(atomic)及其操作应运而生,提供了底层同步操作的功能,其常常只需一两条 CPU 指令即可实现。
1. 内存模型基础内存模型牵涉两个方面:基本结构和并发。基本结构关系到整个程序在内存中的布局。它对并发很重要,尤其是在我们分析 ...
C++ 并发操作的同步
C++ 中并发操作的同步手段主要有三种,按复杂程度从低到高依次为:
std::async;
std::packaged_task;
std::promise。
其中 std::async是函数模板,另外两个为类模板。三者都定义在头文件 <future> 中,且由不可拷贝的 std::future 类型的对象接收事件的结果。
我们逐个介绍上述三种,并在其中顺带演示如何使用 std::future 对象。
1. std::async最简单的方法,std::async 函数接收 1 个可调用对象(通常是函数)以及此调用对象的参数。例如:
12345678910111213#include <iostream>#include <future>int sum(int a, int b) { return a + b;}int main(int, char**) { std::future<int> f = std::async(sum, 3, 4); std::cout << f.g ...
Linux 中查看网络连接信息命令 netstat 的常见用法
1. 命令 netstat 的作用netstat 命令用于打印网络连接、路由表、接口统计、伪装连接和多播成员信息。
因为我本人不是专业搞网络的,我最常用的就是用 netstat 打印网络信息,主要是看看 IP、端口什么的,验证一些程序的网络是否正常等。所以本文要给出的可能也是 netstat 最泛用的几个方法(选项),不管是不是专业搞网络的人应该都在某些场景里会用得上。
本文主要参考自 netstat(8) — Linux manual page 中的查看网络连接部分,其他部分感兴趣可以自己看看。
2. netstat 查看网络连接netstat 查看网络连接信息的命令如下:
1netstat [address_family_options]
其实就是命令 netstat 命令后接地址族选项。默认情况下,netstat 显示打开的套接字列表。如果我们不指定任何地址族,那么将打印所有已配置地址族的活动套接字。
与网络连接信息相关的地址族选项有:
-t --tcp:打印使用 TCP 协议网络连接信息。
-u --udp:打印使用 UDP 协议网络连接信息。
-U --udplite:打印 ...
Linux 中查看进程信息命令 ps 的常见用法
ps 命令用于查看当前进程的快照信息,其功能很多,本文只介绍我个人常用的。完整手册见 ps(1) — Linux manual page。
ps 命令通常需要配合选项使用,如果不加选项的话,只会打印出当前 bash 和 ps 本身的简略进程信息:
1234$ ps PID TTY TIME CMD2057074 pts/0 00:00:00 bash2057151 pts/0 00:00:00 ps
不加选项的 ps 命令通常没什么意义,所以我们需要配合选项使用。
1. 参数的种类与大多程序不同,ps 命令有三种选项种类:
Unix 选项,必须以前缀 - 开始,如 ps -ef。
BSD 选项,必须没有前,如 ps aux。
GNL 长选项,必须以前缀 -- 开始,如 ps --deselect。
不同类型的选项可以自由组合,但使用不当可能会发生冲突。
有一些选项是同义的,功能完全相同,但 ps 的实现中为了兼容性而将这些同义的选项都保留了下来。
由于 ps 选项比较多,本文不打算逐一介绍,而是按场景介绍,讲述每个场景该怎么用(用哪些选项),为什 ...
Unable to load authentication plugin 'caching_sha2_password'
1. 报错信息使用某工具连接 MySQL 服务器时,报错:
1Unable to load authentication plugin 'caching_sha2_password'.
此报错信息翻译过来是说,无法加载身份验证插件 caching_sha2_password。
2. 错误分析此错误的根本原因是:MySQL 在 8 版本后使用了新的身份验证插件 caching_sha2_password,而在 8 以前的身份验证插件是 mysql_native_password。
我这里的 MySQL 版本为 8.0.28,我们可以查看下当前的默认身份验证插件的确是 caching_sha2_password:
1234567mysql> show variables like "default_authentication_plugin";+-------------------------------+-----------------------+| Variable_name | Value ...
配置 NFS 实现 Linux 之间的目录共享
网络文件系统(英语:Network File System,缩写作 NFS)是一种分布式文件系统,力求客户端主机可以访问服务器端文件,并且其过程与访问本地存储时一样,它由Sun Microsystems(已被甲骨文公司收购)开发,于1984年发布。NFS 的实现基于 ONC RPC(一个开放、标准的RFC系统,任何人或组织都可以依据标准实现它)。
本文仅介绍 NFS 最简单的用法:在两台不同的 Linux 机器上共享目录。
而 NFS 那些更复杂的用法基本也都是在此简单用法之上的拓展,深入了解配置,举一反三便能做到。
-
我这里以一个简单地实例的实现,来阐述整个过程:
假设有 A 和 B 两台不同的但可以相互连接的 Linux 服务器(我这里均以 CentOS 系统举例),我们要将 A 服务器上的 /nfs-shared/ 目录共享给 B 服务器。在 B 服务器上,将 A 服务器上共享来的目录,挂载(NFS 是通过挂载的方式来访问共享内容的)到自己 /nfs-shard-from-server/ 目录。完成后,A 服务器访问自己的 /nfs-shared/ 目录,与 B 服务器访问目录 ...
Docker 快速开始与基本用法
本人不是 docker 重度用户,也不是从事运营 docker 或 k8s 相关工作的运维人员。我使用 docker 通常是偶尔试一些东西,避免把服务器环境搞乱;或者是想在一个相对干净的环境中临时编译一个项目等。所以我属于比较轻度的 docker 用户,基本上也就只会用到一些基础功能。本文也不会介绍相对复杂的 Dockerfile 配置。
本文的主要目标是:
从 0 快速启动一个 docker 容器,并使用 ssh 登录该容器。
给出一些 docker 比较常用的操作和容器配置(至少是作为轻度用户的我比较常用的)。
本文使用的 Linux 发行版为 CentOS 8。
另外,docker 的安装和使用默认需要 root 权限,如果你需要在没有权限的用户里使用 docker,请查阅官方文档。
1. 安装 Docker1.1. 卸载旧版本 Docker旧版本的 docker 的包名叫做 docker 或者 docker-engine,我们需要把旧版本的 docker 卸载掉(如果有的话):
12345678sudo yum remove docker \ ...
Linux 一键更换国内软件源
通常我是在自己的 Linux 机器上配置代理的,但是确实也有很多场景配置代理是不容易操作的。
为了能顺利安装一些软件,也只能是换国内软件源咯。
更换国内软件源这件事有大佬编写的脚本我们可以拿来直接用,项目地址是 GitHub 或 Gitee。
基本上各种主流的 Linux 发行版都能用,这里就不多说了,更详细的信息可以看项目地址。这里直接说咋用。
用法非常简单:
12wget https://gitee.com/SuperManito/LinuxMirrors/raw/main/ChangeMirrors.shsudo sh ChangeMirrors.sh
即可进入脚本提供的交互界面,像下面这样:
123456789101112131415161718192021222324252627282930313233343536373839+---------------------------------------------------+| || ================= ...