C++ Copy&Swap 惯用法指南

Copy&Swap 是什么Copy&Swap 是一种 C++ 中常用的编程技巧,用于实现类的赋值运算符(operator=)。 实现传统写法先看看未使用 Copy&Swap 的赋值运算符写法: #include <iostream> #include <vector> class OldAClass { private: int _count; std::string _str; std::vector<int> _vec; public: OldAClass() : _count(0), _vec(10) {} // 拷贝构造函数 和 拷贝赋值运算符 OldAClass(OldAClass &a) : _count(a._count), _str(a._str), _vec(a._vec) { std::cout << "Copy constructor called\n"; } OldAClass &operator=(OldAClass &a) { std::cout << "Copy Assignment operator called\n"; if (this != &a) { //判断传入的 a 是否是自己 _count = a._count; _str = a._str; _vec = a._vec; } return *this; } // 移动构造函数 和 移动赋值运算符 OldAClass(OldAClass &&a) noexcept : _count(a._count), _str(std::move(a._str)), _vec(std::move(a._vec)) { std::cout << "Move constructor called\n"; } OldAClass &operator=(OldAClass &&a) noexcept { std::cout << "Move Assignment operator called\n"; if (this != &a) { _count = a._count; _str = std::move(a._str); _vec = std::move(a._vec); } return *this; } }; 可以看到,这种写法需要重复写两次赋值运算符,并且每次都需要判断传入的参数是否是自己,而且代码重复度高。 Copy&Swap 写法class AClass { private: int _count; std::string _str; std::vector<int> _vec; public: AClass() : _count(0), _vec(10) {} static void swap(AClass &a, AClass &b) { std::swap(a._count, b._count); std::swap(a._str, b._str); std::swap(a._vec, b._vec); } // 拷贝构造函数 AClass(AClass &a) : _count(a._count), _str(a._str), _vec(a._vec) { std::cout << "Copy constructor called\n"; } // 移动构造函数 AClass(AClass &&a) noexcept { std::cout << "Move constructor called\n"; swap(*this, a); } // 赋值运算符 AClass &operator=(AClass a) { // 注意这里的参数是值传递,会调用拷贝构造函数 std::cout << "Assignment operator called\n"; swap(*this, a); return *this; } }; 这种写法只需要写一次赋值运算符,代码更简洁,而且不需要判断传入的参数是否是自己。 ...

2024年01月15日 · 2 min

Jetson (Ubuntu Arm64) 安装 Bazel

简介本文旨在帮助用户在 Jetson 上的 Ubuntu Arm64 系统上安装 Bazel。Bazel 是一个开源的构建工具,它专注于构建和测试大型软件项目,并且被广泛应用于机器学习和深度学习领域。通过使用 Bazel,您可以更高效地管理和构建您的项目。 步骤 1:安装OpenJDK在开始安装 Bazel 之前,我们需要安装 OpenJDK。在终端中执行以下命令: sudo add-apt-repository ppa:webupd8team/java sudo apt-get update sudo apt-get install openjdk-11-jdk 步骤 2:下载 Bazel 安装包在安装 OpenJDK 之后,我们需要下载 Bazel 的安装包。在终端中执行以下命令: wget https://github.com/bazelbuild/bazel/releases/download/6.2.1/bazel-6.2.1-dist.zip 或者,您也可以从 Bazel 的 Github 仓库下载最新版本的安装包。(必须下载dist.zip文件) 步骤 3:安装 Bazel下载完成后,我们可以使用以下命令来安装 Bazel: unzip bazel-6.2.1-dist.zip -d bazel-6.2.1 bash./compile.sh sudo cp output/bazel /usr/local/bin 步骤 4:验证安装安装完成后,我们可以验证 Bazel 是否成功安装。在终端中执行以下命令: bazel version 如果一切正常,您应该能够看到如下输出:

2023年06月14日 · 1 min · Cassius0924

Ubuntu 安装 Protobuf 指南

Protobuf(Protocol Buffers)是一种轻量级的数据交换格式,常用于高效地序列化结构化数据。本指南将介绍如何在 Ubuntu 上安装 Protobuf。 步骤 1:更新系统在安装 Protobuf 之前,我们首先需要确保系统已经更新到最新版本。打开终端并执行以下命令: sudo apt update sudo apt upgrade 这将更新系统的软件包并安装最新的安全补丁。 步骤 2:安装编译工具和依赖项在安装 Protobuf 之前,我们需要安装一些编译工具和依赖项。执行以下命令来安装它们: sudo apt install build-essential autoconf libtool 这些工具和依赖项将帮助我们编译和构建 Protobuf。 步骤 3:下载和编译 Protobuf 首先,我们需要下载 Protobuf 的源代码。这里选择下载v3.20.3版本的Protobuf源码压缩包。(必须下载-all压缩包) 解压压缩包 tar -zxvf protobuf-all-3.20.3.tar.gz 这将克隆 Protobuf 的源代码到当前目录。 进入克隆下来的 Protobuf 目录: cd protobuf-all-3.20.3 在源代码目录中,运行以下命令来生成配置文件和构建系统: ./autogen.sh 接下来,我们需要运行 configure 脚本来配置编译选项。可以使用以下命令进行配置: ./configure 配置完成后,我们可以使用以下命令编译和安装 Protobuf: sudo make sudo make check #这一步可能会报错,解决方法见下文 sudo make install sudo ldconfig 编译过程可能需要一些时间,请耐心等待。 步骤 4:验证安装安装完成后,我们可以验证 Protobuf 是否成功安装。执行以下命令来检查 Protobuf 的版本信息: ...

2023年06月12日 · 1 min · Cassius0924

解决 Open3D 同时链接其他库时的 Undefined Reference 错误

当你的 Open3D 项目同时使用了 OpenCV 或 Protobuf 等其他库时,在链接库时可能会出现 Undefined Reference 的错误。这是因为 Open3D 默认使用的 C++ ABI 版本与其他库不一致导致的。 为了解决这个问题,可以在重新编译安装 Open3D 时打开 -DGLIBCXX_USE_CXX11_ABI=ON 选项,即使用 C++11 ABI 版本。以下是具体的步骤: 解决方法找到 Open3D 源码cd open3d 找不到请在 Github 上重新下载。 重新编译安装 Open3D进入 Open3D 的源代码目录的 build 子目录进行编译安装。 cd build 在 build 子目录中执行 CMake 命令生成 Makefile。在命令行中添加 -DGLIBCXX_USE_CXX11_ABI=ON 选项。 cmake .. -DBUILD_SHARED_LIBS=ON -DGLIBCXX_USE_CXX11_ABI=ON -DCMAKE_BUILD_TYPE=Release 最后,执行 make 命令编译并安装 Open3D。 make -j6 sudo make install 使用 Open3D重新编译安装后的 Open3D 就能够正常链接其他库了。

2023年06月09日 · 1 min · Cassius0924

Unity 脚本使用 NuGet 安装解决方案包

本文旨在教大家如何在 Unity 中使用 NuGet 安装解决方案包。 Visual Studio 集成了 NuGet 管理器,可以方便的安装和卸载解决方案包。但在使用 Viusal Studio 开发 Unity C# 脚本时,不能直接在内置的 NuGet 管理器安装解决方案包。因为 Unity 工程打开或运行时会刷新工程文件,导致我们在 Visual Studio 内置 NuGet 管理器安装的解决方案包失效。所以 Unity 使用 NuGet 安装解决方案包需要特殊步骤。 步骤下载解决方案包在NuGet官网下载你需要解决方案包,例如Google.Protobuf。 直接下载会下载最新预览版,稳定版需要点击右上角的 Full stats,查看所有版本。 找到稳定版 3.22.4,点击即可下载。 解压包下载后会得到拓展名为.nupkg的文件,先将文件拓展名改为.zip,接着解压即可。 导入dll文件解压后可以得到 dll 文件,位于 google.protobuf.3.22.4/lib/**/Google.Protobuf.dll ,将dll文件复制到 Unity 工程文件夹的 Assets/Plugins 文件夹下,若没有这个文件夹自己手动新建一个。 配置Unity项目接着需要将 Unity 项目的 Api Compatibility Level 更改为与 dll 文件对应的版本。打开 Unity 的 Project Settings,找到 Player > Other Settings > Api Compatibility Level。 ...

2023年06月01日 · 1 min · Cassius0924

垃圾代码书写准则

这是一个你的项目应该遵循的垃圾代码书写准则的列表,把称为适当的垃圾代码。 来自GitHub开源项目State-of-the-art。 准则💩 以一种代码已经被混淆的方式命名变量如果我们键入的东西越少,那么就有越多的时间去思考代码逻辑等问题。 Good 👍🏻 let a = 42; Bad 👎🏻 let age = 42; 💩 多用拼音命名变量和函数写拼音多方便,我们要推崇。 Good 👍🏻 function hqtpgd(tp) { //获取图片高度 return tp.height; //图片 } Bad 👎🏻 function getImageHeight(image) { return image.height; } 💩 变量/函数混合命名风格为不同庆祝一下。 Good 👍🏻 let wWidth = 640; let w_height = 480; Bad 👎🏻 let windowWidth = 640; let windowHeight = 480; 💩 不要写注释反正没人会读你的代码。 Good 👍🏻 const cdr = 700; Bad 👎🏻 更多时候,评论应该包含一些“为什么”,而不是一些“是什么”。如果“什么”在代码中不清楚,那么代码可能太混乱了。 // 700ms的数量是根据UX A/B测试结果进行经验计算的。 // @查看: <详细解释700的一个链接> const callbackDebounceRate = 700; 💩 使用母语写注释如果您违反了“无注释”原则,那么至少尝试用一种不同于您用来编写代码的语言来编写注释。如果你的母语是英语,你可能会违反这个原则。 Good 👍🏻 // Закриваємо модальне віконечко при виникненні помилки. toggleModal(false); Bad 👎🏻 // 隐藏错误弹窗 toggleModal(false); 💩 尽可能混合不同的格式为不同庆祝一下。 Good 👍🏻 ...

2023年04月21日 · 4 min · Cassius0924

Linux 命令行网络连接指南

本文旨在为 Linux 用户介绍提供关于使用命令行连接网络的方法。 本文将详细介绍利用 nmcli 工具连接 Wi-Fi 和以太网的教程,包括查看连接状态、控制 Wi-Fi、控制以太网等等。 安装 nmclinmcli 是 NetworkManager 的命令行工具,它可以用于管理和配置网络连接。如果你的 Linux 系统上没有安装 nmcli,请使用以下命令进行安装: sudo apt-get install network-manager 查看连接状态在连接网络之前,我们需要先查看网络状态。使用以下命令可以查看当前网络状态: nmcli general status 以上命令可以简写为: nmcli g # g 表示 general,默认为 status STATE:这是 NetworkManager 的当前状态。它可以是 “connected”、“connecting”、“disconnected”、“disconnecting” 或 “asleep” 等。 Connectd Connecting Disconnected Disconnecting Asleep 已连接 连接中 未连接 断连中 休眠 CONNECTIVITY:这是系统的网络连接状态。它可以是 “full”、“limited” 、“Portal” 或 “none”。 Full Limited Portal None 已联网,可上网 已联网,但不可上网 已联网,但需要认证 未联网 WIFI-HW:这是 WiFi 硬件的状态。它可以是 “enabled” 或 “disabled”。 ...

2023年04月14日 · 2 min · Cassius0924

MacOS 修改 App Store 和地图软件语言指南

在 macOS 系统设置中,我们可以轻松地设置软件的语言,但有些应用程序如 App Store 和 Maps 却无法直接在设置中修改语言。这可能会让我们在使用这些应用程序时感到困惑,尤其是当我们需要使用不同语言的应用程序时。 本文提供了一种简单的方法,让您能够修改 App Store 和 Maps 的语言设置,以便在需要时更轻松地使用这些应用程序。 修改方法修改苹果地图的语言为简体中文: sudo defaults write com.apple.Maps AppleLanguages '("zh-CN")' 修改 App Store 的语言为美式英语: sudo defaults write com.apple.AppStore AppleLanguages '("en-US")' 其他软件其他软件均可在系统设置里直接设置。 其他语言同理,其他语言只需修改命令最后的**「语言区域码」**即可。 语言名称 代码 中文(简体) zh-CN 中文(繁体) zh-TW 英语(美国) en-US 英语(英国) en-GB 日语 ja 法语 fr 德语 de 西班牙语 es 韩语 ko 俄语 ru 葡萄牙语(巴西) pt-BR 阿拉伯语 ar 意大利语 it 土耳其语 tr 印地语 hi 印尼语 id 荷兰语 nl 波兰语 pl 瑞典语 sv 丹麦语 da 芬兰语 fi 挪威语 no 希腊语 el

2023年04月14日 · 1 min · Cassius0924

MacOS 配置 MASM + DOSBox 汇编环境

该文章旨在帮助在 MacOS 系统下想要学习汇编语言的开发者配置 MASM + DOSBox 环境。 配置步骤 克隆该项目到本地: git clone https://github.com/cassius0924/MASMForMac.git 将项目文件夹移动某个位置: 例如我将这个文件夹放到了 ~/Documents/中 mv MASMForMac ~/Documents/. 安装 DOSBox: 用 Finder 打开 MASMForMac/mac 目录,打开 dmg 安装包。再打开 Application 文件夹,将 DOSBox 应用程序拖入 Application 文件夹中。 在 DOSBox 中挂载目录: mount c ~/Documents/MASMForMac 此目录将会把~/Documents/MASMForMac挂载到 C 盘。路径根据自己情况修改。 每次打开 DOSBox 应用程序都需要挂载目录。可以配置自动挂载,详见下文**「配置文件」**。 在 DOSBox 中进入 C 盘: c: 编译 hello.asm 文件: 已经预先写好了一个hello.asm汇编测试示例,用于测试汇编环境。 masm hello.asm 连按三下回车,此命令会生成obj文件。 生成hello.exe可执行文件: link hello.obj 同样连按三下回车。 运行 hello.exe 文件: hello.exe 正常情况,会输出字符串:Hello world! ...

2023年04月12日 · 1 min · Cassius0924

基于 Open3D C++ 版实现点云数据的配准、相加和显示

本文介绍如何使用 Open3D C++ 库来进行点云的配准、相加和可视化显示。Open3D 是一个开源的多维数据处理工具箱,支持点云、图像和三维几何等多种类型的数据处理和可视化。 点云读取使用 ReadPointCloud() 函数可以轻松读取 pcd 和 ply 点云文件: // 读取 pcd 和 ply 点云文件 auto source = std::make_shared<open3d::geometry::PointCloud>(); auto target = std::make_shared<open3d::geometry::PointCloud>(); open3d::io::ReadPointCloud("pcd-data/1.pcd", *source); open3d::io::ReadPointCloud("pcd-data/2.pcd", *target); // ply 文件同理 // open3d::io::ReadPointCloud("pcd-data/1.ply", *source); // open3d::io::ReadPointCloud("pcd-data/2.ply", *target); 点云上色为两份点云上上不同的颜色: source->PaintUniformColor({1, 0.706, 0}); // source 为黄色 target->PaintUniformColor({0, 0.651, 0.929});// target 为蓝色 点云配准使用 Open3D 提供的 RegistrationICP() 函数进行点云配准。代码如下: // 为两个点云分别进行outlier removal //auto processed_source = source->RadiusOutlierRemoval(16, 0.5); //auto processed_target = target->RadiusOutlierRemoval(16, 0.5); double threshold = 1.0; // 移动范围的阀值 Eigen::Matrix4d trans_init = Eigen::Matrix4d::Identity(); // 运行ICP配准 open3d::pipelines::registration::RegistrationResult reg_p2p; // 这一步会返回点云的变换矩阵 reg_p2p = open3d::pipelines::registration::RegistrationICP( *source, *target, threshold, trans_init, open3d::pipelines::registration::TransformationEstimationPointToPoint()); // 将点云依照输出的变换矩阵进行变换 source->Transform(reg_p2p.transformation_); 点云相加这一步很简单,使用重载运算符 += 将两份点云数据相加: ...

2023年04月10日 · 1 min · Cassius0924