【编程】C++语言编程规范-2

编程实践

结合C++ Effective系列参考树、尤其是工程经验教训的总结。

并发

  • 除非必要,尽量少用线程。
  • 多线程编程要守护好内存,使用atomic、mutex、condition variable、future、semaphore、latch、barrier等同步机制避免数据竞争。
  • 尽量缩小临界区,临界区指独占的资源,禁止其他线程访问变量的代码片段,如持有mutex的作用域。与回调函数相似,应尽可能精简此类操作,避免执行耗时的处理、阻塞性操作如sleep。能在临界区、回调函数外处理的,尽可能在外部。
  • 必须正确管理多线程中的对象,避免某线程正在访问的对象被另一线程清理,如用move方法使对象从一个线程正确移交给另一个线程,避免内存泄漏。
  • 使用condition variable时,必须增加条件判断并在循环中等待。下例中,线程ReceivingUnPro中条件变量错过了通知,缺少条件判断,就始终处于等待状态,而ReceivingPro依靠while判断条件,解决了问题。
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>std::condition_variable g_dataCond;
std::string g_words = "";
std::mutex g_mtx;
bool g_isReady = false;void ReceivingUnpro() {std::unique_lock<std::mutex> lg(g_mtx);std::cout << "waiting!" << std::endl;g_dataCond.wait(lg);std::cout << "Bad receiving thread got the message: " << g_words<< std::endl;
}
void ReceivingPro() {std::unique_lock<std::mutex> lg(g_mtx);while (!g_isReady) {g_dataCond.wait(lg);}std::cout << "Protected receiving thread got the message: " << g_words<< std::endl;
}
void Sending() {std::lock_guard<std::mutex> lg(g_mtx);g_words.append("Go forward!");g_isReady = true;g_dataCond.notify_all();
}
int main() {std::thread b(Sending);b.join();std::thread ap(ReceivingPro);ap.join();std::thread a(ReceivingUnpro);a.join();return 0;
}

理论上,条件变量有虚假唤醒问题,所以要条件判断避免。

  • 用std::lock_gaurd、std::unique_lock确保锁被释放,不要用std::mutex的lock()、unlock()以免遗忘或异常导致dead lock。
    错误的例子,
#include <mutex>
std::mutex x;
{x.lock();// 处理数据的代码// 发生异常,导致后面未执行x.unlock(); 
}

下例中出现dead lock,

#include <unistd.h>
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>using std::cout;
using std::endl;
using std::lock_guard;
using std::mutex;
using std::chrono::seconds;mutex m1, m2, m3;
std::condition_variable cnd;
std::mutex dt_mtx;
bool ready = false;
std::vector<int> vec_i;void ProcessData() {for (const auto i : vec_i) {std::cout << i << " ";}std::cout << std::endl;
}void T1F() {std::unique_lock<std::mutex> lock(dt_mtx);cnd.wait(lock, [] { return ready; });ProcessData();
}void T2F() {{std::lock_guard<std::mutex> lock(dt_mtx);for (int i = 0; i < 10; i++) {vec_i.push_back(i);sleep(1);}ready = true;}cnd.notify_all();
}void Fun1() {lock_guard<mutex> l1(m1);std::this_thread::sleep_for(seconds(1));lock_guard<mutex> l2(m2);std::this_thread::sleep_for(seconds(1));cout << "Fun1 is finishing" << endl;
}
void Fun2() {lock_guard<mutex> l1(m2);std::this_thread::sleep_for(seconds(1));lock_guard<mutex> l2(m3);std::this_thread::sleep_for(seconds(1));cout << "Fun2 is finishing" << endl;
}
void Fun3() {lock_guard<mutex> l1(m3);std::this_thread::sleep_for(seconds(1));lock_guard<mutex> l2(m1);std::this_thread::sleep_for(seconds(1));cout << "Fun3 is finishing" << endl;
}
int main() {std::thread t1(Fun1);std::thread t2(Fun2);std::thread t3(Fun3);if (t1.joinable()) {cout << "t1 is joining" << endl;t1.join();}if (t2.joinable()) {cout << "t2 is joining" << endl;t2.join();}if (t3.joinable()) {cout << "t3 is joining" << endl;t3.join();}
#ifdef VERSION1std::thread t1(T1F);std::thread t2(T2F);t1.join();t2.join();
#endifreturn 0;
}

对象与内存管理

  • 避免访问越界,如索引数组前判断下标是否超出数组区间。
  • 申请内存要先检查大小。
  • 数组作为函数参数,若是已知的固定长度,建议用std::array;若不确定长度,传递来的数组表现为指针,则函数参数要加上数组长度,或者将数组的指针与长度封装为一个类。
  • 避免函数返回其局部变量的地址,建议改为返回复制的值。
  • lambda的作用范围超出局部时,如用于线程等,按引用捕获可能导致局部变量过早被清理,应改为按值捕获;应明确捕获的变量、合理的捕获类型。

常量

  • 建议优先用constexpr定义常量,编译时硬编码变量,提升效率;改关键字要求被修饰对象在编译时可确定变量的值。
  • 使用const修饰函数内部不会修改的参数,类内不变的变量、不修改不可变的成员变量的成员方法。
  • const实例化的对象,只允许调用其const方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/691981.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智慧社区管理系统:构建未来的生活模式

在这个信息化、智能化的时代&#xff0c;我们期待的不再是简单的居住空间&#xff0c;而是一个集安全、便捷、舒适、环保于一体的智能化社区。为此&#xff0c;我们推出了全新的智慧社区管理系统&#xff0c;旨在将先进的科技力量引入社区管理&#xff0c;为居民提供更优质的生…

OpenProject + Rocky8安装

文章目录 1、概要2、整体架构流程3、准备4、安装5、openproject 配置5.1、第一步&#xff1a;OpenProject 版本选择5.2、第二步&#xff1a;PostgreSQL 支持5.3、第三步&#xff1a;Apache2 Web 服务器支持5.4、第四步&#xff1a;hostname 支持5.5、 第五步&#xff1a;服务器…

从零学算法172

172.给定一个整数 n &#xff0c;返回 n! 结果中尾随零的数量。 提示 n! n * (n - 1) * (n - 2) * … * 3 * 2 * 1 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;0 解释&#xff1a;3! 6 &#xff0c;不含尾随 0 示例 2&#xff1a; 输入&#xff1a;n 5 输出&…

【Docker】Docker存储卷

文章目录 一、什么是存储卷二、为什么需要存储卷三、存储卷分类四、管理卷Volume创建卷方式一&#xff1a;Volume 命令操作方式二&#xff1a;-v 或者--mount 指定方式三&#xff1a;Dockerfile 匿名卷 操作案例Docker 命令创建管理卷Docker -v 创建管理卷Docker mount 创建管理…

懒加载实践记录

1.原理 懒加载的原理是通过监听用户的浏览行为&#xff0c;当用户滚动到可视区域内时&#xff0c;再进行资源的加载。这样可以避免一次性加载过多的资源&#xff0c;从而减少页面的加载时间和带宽消耗。 2.主要使用场景 懒加载适用于图片较多&#xff0c;页面列表较长(长列表)…

Linux——常用特殊符号介绍

1、# 井号 (comments) 这几乎是个满场都有的符号&#xff0c;除了先前已经提过的"第一行" #!/bin/bash 井号也常出现在一行的开头&#xff0c;或者位于完整指令之后&#xff0c;这类情况表示符号后面的是注解文字&#xff0c;不会被执行。 # This line is comments.…

unity学习(32)——跳转到角色选择界面(父子类问题)

新问题 应该是两个脚本之间缺少继承关系 its children 解决起来很简单&#xff0c;把ResceneScript也绑到canvas上就可以了 。 此时&#xff0c;在账号密码正确的情况下&#xff0c;是可以完成场景切换。 对应的代码如下&#xff1a; TMP_Text d GameObject.FindWithTag(&…

嵌入式Linux学习DAY20

文件io 文件io和标准io的区别&#xff1a; 1.标准io是库函数&#xff0c;是对系统调用的封装 2.文件io是系统的调用&#xff0c;是Linux内核中的函数接口 3.标准io是有缓存的 4.文件io是没有缓存的 操作步骤 打开->读写->关闭 打开文件&#xff1a;open 功能&am…

了解不同颜色油封的用途

在机械领域&#xff0c;油封是保证各种设备平稳运行的关键部件。为什么油封会有很多颜色。本文旨在阐明不同颜色油封的用途及其意义。 油封有多种颜色&#xff0c;包括黑色、棕色、绿色和蓝色等。乍一看&#xff0c;这些颜色似乎只是一种审美选择。然而&#xff0c;它们有更实…

接口测试(postman/jmeter)

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、什么是接口测试 通常做的接口测试指的是系统对外的接口&am…

Window部署Nacos

Nacos 现在压缩包解压后&#xff0c;修改conf/application.properties 文件 取消注释&#xff0c;修改mysql连接方式 节点nacos.core.auth.enabled 改成true 设置节点nacos.core.auth.server.identity.key、nacos.core.auth.server.identity.value 设置secret秘钥&#xff0c;…

十大常见web漏洞及防范

十大常见web漏洞 一、SQL注入漏洞 SQL注入攻击&#xff08;SQL Injection&#xff09;&#xff0c;简称注入攻击、SQL注入&#xff0c;被广泛用于非法获取网站控制权&#xff0c;是发生在应用程序的数据库层上的安全漏洞。在设计程序&#xff0c;忽略了对输入字符串中夹带的S…

javascript选择器大全

目录 1.getElementsByTagName 2.getElementsByName 3.getElementById 4.getElementsByClassName 5.querySelector 6.querySelectorAll 1.getElementsByTagName 俗称标签选择器&#xff0c;可以根据标签名查找匹配到页面的元素对象&#xff0c;返回为一个数组。 <div&…

如何使用静态住宅ip代理进行Facebook群控?

在进行Facebook群控时&#xff0c;ip地址的管理是非常重要的&#xff0c;因为Facebook通常会检测ip地址的使用情况&#xff0c;如果发现有异常的使用行为&#xff0c;比如从同一个ip地址频繁进行登录、发布内容或者在短时间内进行大量的活动等等&#xff0c;就会视为垃圾邮件或…

springcloud-远程调用

微服务的远程调用 RestTemplate 在项目中&#xff0c;当我们需要远程调用一个 HTTP 接口时&#xff0c;我们经常会用到 RestTemplate 这个类。这个类是 Spring 框架提供的一个工具类。 实例化RestTemplate 创建配置类&#xff0c;实例化RestTemplate Configuration public clas…

【递归】:原理、应用与案例解析 ,助你深入理解递归核心思想

递归 1.基础简介 递归在计算机科学中&#xff0c;递归是一种解决计算问题的方法&#xff0c;其中解决方案取决于同一类问题的更小子集 例如 递归遍历环形链表 基本情况&#xff08;Base Case&#xff09;&#xff1a;基本情况是递归函数中最简单的情况&#xff0c;它们通常是递…

揭示端侧大语言模型的无限潜力:多种量化模型,可以在个人电脑或者手机上安装部署使用,几行代码进行调研可以离线使用

揭示端侧大语言模型的无限潜力:多种量化模型,可以在个人电脑或者手机上安装部署使用,几行代码进行调研可以离线使用。 MiniCPM 是面壁智能与清华大学自然语言处理实验室共同开源的系列端侧大模型,主体语言模型 MiniCPM-2B 仅有 24亿(2.4B)的非词嵌入参数量, 总计2.7B参数…

频段划分学习射频知识的意义

一、射频电路设计与低频电路设计的不同点 随着频率提高&#xff0c;相应电磁波的波长与变得可与分立电路元件的尺寸相比拟时&#xff0c;电阻、电容和电感这些元件的电响应&#xff0c;将偏离他们的理想频率特性。以 WIFI 2.4G 频段为例&#xff0c;当频率为 2437MHz&#xff0…

Ubuntu安装wireguard服务端,windows连接

需求&#xff1a;想要随时随地远程到ubuntu电脑的内网中&#xff0c;ping通所有的内网ip&#xff0c;方便通过内网ip进行远程 一、ubuntu上安装配置wireguard服务 1&#xff0c;更新软件包并安装wireguard服务端软件 sudo apt update sudo apt install wireguard 2&#xff0…

Flutter学习1 - Android开发者快速上手

1、对应关系 概念对应关系 AndroidFlutter页面Activity和FragmentWidget视图ViewWidget页面跳转IntentNavigater网络库okHttphttp数据存储SharedPreference和SQLiteshared_preferences和sqflite 布局对应关系 AndroidFlutter布局文件xmlWidget线性布局LinearLayoutRow和Col…