高质量C/C++代码心得

news2024/11/28 23:56:03

写出高质量的C/C++代码是一个涉及多方面的任务,它要求程序员不仅具备扎实的语言基础,还需要掌握一系列的软件设计和开发原则。下面将详细介绍如何写出高质量的C/C++代码,并通过10个例子进行具体阐述。
在这里插入图片描述

一、编码规范

编写高质量的代码,首先要遵循一定的编码规范。这不仅可以提高代码的可读性,还有助于减少错误和提高维护效率。主要的编码规范包括:

  1. 命名规范:变量、函数、类等命名要清晰、准确,能反映其含义或用途。
  2. 缩进与空格:保持一致的缩进风格,比如使用4个空格或1个制表符。
  3. 注释:对复杂逻辑或关键部分添加注释,解释代码的作用和实现原理。
  4. 函数长度与复杂度:尽量保持函数简短,逻辑清晰,避免过长的函数和复杂的嵌套结构。

二、资源管理

在C/C++中,资源管理是一个重要环节。不正确的资源管理会导致内存泄漏、资源耗尽等问题。以下是几个关键点:

  1. 内存管理:确保动态分配的内存被正确释放,避免内存泄漏。使用智能指针(如std::unique_ptrstd::shared_ptr)可以简化内存管理。
  2. 文件与网络连接:及时关闭打开的文件和网络连接,避免资源泄露。
  3. 异常处理:合理使用异常处理机制,确保程序在异常情况下的稳定性和资源释放。

三、性能优化

写出高质量的代码,不仅要考虑程序的正确性,还要关注性能。以下几点有助于提高性能:

  1. 算法选择:选择合适的算法和数据结构,降低时间复杂度和空间复杂度。
  2. 避免不必要的拷贝:使用引用和指针传递大对象,避免不必要的拷贝开销。
  3. 利用语言特性:使用C++的RAII(Resource Acquisition Is Initialization)机制管理资源,利用模板元编程优化编译时性能等。

四、安全性

安全性是高质量代码不可或缺的一部分。以下是几个提高安全性的建议:

  1. 防止缓冲区溢出:对于字符数组等缓冲区操作,要确保不越界访问。
  2. 检查输入:对于外部输入(如用户输入或网络数据),要进行有效性检查,防止注入攻击等安全问题。
  3. 使用安全函数库:如使用C++的STL库而不是C风格的字符串操作,以减少潜在的安全风险。

五、10个例子详解

以下通过10个例子具体说明如何写出高质量的C/C++代码:

  1. 清晰的命名:例如,使用calculateAverage()而不是calcAvg()来明确表示函数的作用。
  2. 有意义的注释:对于复杂的算法或逻辑,添加注释解释其工作原理和实现细节。
  3. 使用const修饰符:对于不应被修改的值或对象,使用const修饰符可以提高代码的可读性和安全性。
  4. 智能指针管理内存:例如,使用std::unique_ptr自动管理动态分配的内存,避免手动释放造成的错误。
  5. 异常处理:在可能出现错误的操作(如文件读写)中使用try-catch语句进行异常处理。
  6. 算法优化:选择合适的算法和数据结构,例如使用哈希表替代线性搜索以提高效率。
  7. 避免拷贝:对于大对象或容器,使用引用或指针传递,而不是值传递,以减少拷贝开销。
  8. 检查输入有效性:对于用户输入或外部数据,进行检查以确保其有效性和安全性。
  9. 使用安全函数库:例如,使用std::string替代C风格的字符串操作,减少缓冲区溢出的风险。
  10. RAII管理资源:通过构造函数获取资源,析构函数释放资源的方式自动管理资源(如文件句柄、网络连接等)。

案例代码详细说明

1. 清晰的命名

// Bad
int calcAvg(int a, int b) {
    return (a + b) / 2;
}

// Good
double calculateAverage(int num1, int num2) {
    return (num1 + num2) / 2.0;
}

执行calculateAverage函数接收两个整数,计算它们的平均值并返回。函数名清晰地表达了其功能。

2. 有意义的注释

// 计算两个数的最大公约数
int gcd(int a, int b) {
    if (b == 0) return a;
    return gcd(b, a % b);
}

执行gcd函数使用递归方法计算两个整数的最大公约数。注释解释了函数的目的和实现方法。

3. 使用const修饰符

const double PI = 3.14159;
void calculateCircumference(const double& radius) {
    double circumference = 2 * PI * radius;
    // ... 使用circumference进行其他操作 ...
}

执行calculateCircumference函数接收一个常量引用作为半径,并计算圆的周长。使用const确保radius在函数内部不会被修改。

4. 智能指针管理内存

#include <memory>
class MyClass {};
void useSmartPointer() {
    std::unique_ptr<MyClass> obj = std::make_unique<MyClass>();
    // ... 使用obj ...
    // 自动释放内存,无需手动delete
}

执行useSmartPointer函数使用std::unique_ptr智能指针创建和管理MyClass对象的内存。当智能指针超出范围时,它会自动释放内存。

5. 异常处理

#include <iostream>
#include <fstream>
void readFile(const std::string& filename) {
    std::ifstream file(filename);
    if (!file.is_open()) {
        throw std::runtime_error("无法打开文件");
    }
    // ... 读取文件内容 ...
}

执行readFile函数尝试打开一个文件。如果文件无法打开,它会抛出一个异常,可以在调用处使用try-catch语句进行处理。

6. 算法优化

#include <unordered_map>
#include <vector>
int findIndex(const std::vector<int>& nums, int target) {
    std::unordered_map<int, int> hashMap;
    for (size_t i = 0; i < nums.size(); ++i) {
        hashMap[nums[i]] = i; // 使用哈希表存储元素和索引的映射关系,以便快速查找。
    }
    // 在哈希表中查找目标元素,时间复杂度为O(1)。
    if (hashMap.find(target) != hashMap.end()) {
        return hashMap[target]; // 返回目标元素的索引。
    } else {
        return -1; // 如果目标元素不存在于数组中,则返回-1。
    }
}

执行:此代码首先遍历数组并使用哈希表存储每个元素及其索引的映射关系。然后,它在哈希表中查找目标元素,从而实现O(1)时间复杂度的查找性能。如果没有找到目标元素,则返回-1。通过优化算法和数据结构的选择,代码提高了查找效率。这有助于在处理大型数据集或需要快速响应的场景中提升代码质量。通过空间换时间的方式,该代码示例展示了如何在特定情境下实现性能优化。请注意,在实际应用中,还需要考虑内存使用等其他因素来综合评估算法的优劣。总的来说,这是一个利用哈希表优化查找性能的典型例子。
7. 避免拷贝对于大对象或容器使用引用或指针传递而不是值传递以减少拷贝开销。
#include void processLargeData(const std::vector& data)
{
// 使用引用传递大对象避免拷贝开销
// … 对data进行处理 …
}
int main()
{
std::vector largeData(1000000, 1);
// 假设这是一个大对象processLargeData(largeData);
// 通过引用传递避免拷贝
return 0;
}
执行:在main函数中创建了一个包含大量数据的大对象largeData然后通过引用将其传递给processLargeData函数进行处理。使用引用传递避免了对象的拷贝开销提高了效率。
**8. 检查输入有效性对于用户输入或外部数据进行检查以确保其有效性和安全性。
**#include #include void processUserInput(int input) {if (input < 0 || input > 100) {throw std::invalid_argument(“输入值必须在0到100之间”);}// … 对有效输入进行处理 …}int main() {int userInput;std::cin >> userInput;try {processUserInput(userInput);} catch (const std::invalid_argument& e) {std::cerr << "无效输入: " << e.what() << std::endl;return 1;}}
执行:程序首先接收用户输入然后调用processUserInput函数进行处理。在该函数中首先检查输入值是否在有效范围内如果不在则抛出一个异常。在main函数中使用try-catch语句捕获异常并输出错误信息然后结束程序。
**9. 使用安全函数库例如使用std::string替代C风格的字符串操作减少缓冲区溢出的风险。
**#include #include void safeStringOperation() {std::string str1 = “Hello”;std::string str2 = “World”;
std::string result = str1 + " " + str2; // 使用std::string进行字符串拼接
std::cout << result << std::endl;
}
int main()
{
safeStringOperation();
return 0;
}
执行:程序定义了两个字符串str1str2然后使用std::string的拼接操作符将它们连接成一个新的字符串result并输出到控制台。使用std::string进行字符串操作可以避免C风格字符串操作中常见的缓冲区溢出问题提高了安全性。
**10. RAII管理资源通过构造函数获取资源析构函数释放资源的方式自动管理资源(如文件句柄、网络连接等)。
好的,以下是一个完整的RAII(Resource Acquisition Is Initialization)管理资源的案例10,通过构造函数获取资源,析构函数释放资源的方式自动管理资源(如文件句柄、网络连接等)。

#include <iostream>
#include <fstream>

class ResourceHolder {
private:
    std::fstream file;

public:
    ResourceHolder(const std::string& filename) {
        // 在构造函数中打开文件
        file.open(filename, std::ios::out);

        if (!file.is_open()) {
            throw std::runtime_error("Failed to open file.");
        }
    }

    ~ResourceHolder() {
        // 在析构函数中关闭文件
        file.close();
    }

    void writeData(const std::string& data) {
        // 写入数据到文件
        file << data;
    }
};

int main() {
    try {
        // 创建ResourceHolder对象,自动打开文件
        ResourceHolder rh("example.txt");

        // 写入数据到文件
        rh.writeData("Hello, World!");

        // ResourceHolder对象离开作用域,自动关闭文件
    } catch (const std::exception& e) {
        std::cerr << "Exception: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}

在这个案例中,我们定义了一个名为ResourceHolder的类,它负责自动管理文件的打开和关闭。在构造函数中,我们打开了一个名为example.txt的文件,并将其存储在file成员变量中。如果文件打开失败,我们将抛出一个异常。在析构函数中,我们关闭了文件。writeData成员函数用于向文件中写入数据。在main函数中,我们创建了一个ResourceHolder对象,并调用writeData函数向文件中写入数据。当ResourceHolder对象离开作用域时,析构函数会自动被调用,从而关闭文件。这样,我们就通过RAII的方式实现了资源的自动管理。

综上所述,写出高质量的C/C++代码需要综合考虑编码规范、资源管理、性能优化和安全性等方面。通过遵循这些原则并付诸实践,程序员可以编写出既高效又安全的代码。

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

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

相关文章

Learning Semantic-Aware Knowledge Guidance forLow-Light Image Enhancement

微光图像增强&#xff08;LLIE&#xff09;研究如何提高照明并生成正常光图像。现有的大多数方法都是通过全局和统一的方式来改善低光图像&#xff0c;而不考虑不同区域的语义信息。如果没有语义先验&#xff0c;网络可能很容易偏离区域的原始颜色。为了解决这个问题&#xff0…

Linux 定时删除过期文件

需求说明 每日凌晨0点定时删除/temp目录下的所有一个月未被访问的文件。 脚本实现 linux 终端输入crontab -e&#xff0c;添加定时任务脚本命令 [rootlocalhost ~]# crontab -e在文件末尾追加 0 0 * * * find /temp -atime 30 -exec rm -rf {} \;参数说明 命令格式&#…

计算机网络(1):开始

计算机网络&#xff08;1&#xff09;&#xff1a;开始 计算机网络在信息时代中的作用 21世纪的一些重要特征就是数字化、网络化和信息化&#xff0c;是一个以网络为核心的信息时代。要实现信息化就必须依靠完善的网络&#xff0c;因为网络可以非常迅速地传递信息。因此网络现…

BAQ压缩原理

什么是BAQ? BAQ——Block Adaptive Quantization,块自适应量化 BAQ是一种数据压缩算法。 谁提出了BAQ压缩? BAQ压缩原理是由美国NASA JPL的R. Kwok和W.T.K. Johnson在1989年提出的。第一次被用于美国NASA的“麦哲伦金星探测”任务中。 BAQ压缩的目的是什么? 上世纪后半…

使用Python进行文本处理:深入探索文本分析和操作

更多Python学习内容&#xff1a;ipengtao.com 大家好&#xff0c;我是彭涛&#xff0c;今天为大家分享 使用Python进行文本处理&#xff1a;深入探索文本分析和操作&#xff0c;全文3800字&#xff0c;阅读大约12分钟。 文本处理是数据科学和自然语言处理中的关键任务之一。Pyt…

【Mode Management】ComM详细介绍

目录 1. Introduction and functional overview 2.Dependencies to other modules 3.Functional specification 3.1 Partial Network Cluster Management 3.2 ComM channel state machine 3.2.1 Behaviour in state COMM_NO_COMMUNICATION 3.2.1.1 COMM_NO_COM_NO_PENDI…

【Qt QML入门】TextInput

TextInput&#xff1a;单行文本输入框。 TextInput除了光标和文本外&#xff0c;默认没有边框等效果。 import QtQuick import QtQuick.Window import QtQuick.ControlsWindow {id: winwidth: 800height: 600visible: truetitle: qsTr("Hello World")//单行文本输…

typescript使用解构传参

看下面这个函数 interface Student {id: number;name: string;class: string;sex: string;}function matriculation(student: Student) {//...}我们要调用它,就需要传递一个实现了Student约束的对象进去 interface Student {id: number;name: string;class: string;sex: string…

【算法】算法题-20231211

这里写目录标题 一、387. 字符串中的第一个唯一字符二、1189. “气球” 的最大数量三、1221. 分割平衡字符串 一、387. 字符串中的第一个唯一字符 简单 给定一个字符串 s &#xff0c;找到 它的第一个不重复的字符&#xff0c;并返回它的索引 。如果不存在&#xff0c;则返回…

uniapp实现地图电子围栏功能

该功能使用uniapp中内置组件map实现 效果图预览&#xff1a; 实现过程&#xff1a; 1.文档&#xff1a; 2.代码&#xff1a; <template><view><map :style"width: 100%; height:screenHeight" :latitude"latitude" :longitude"longit…

lightdb 23.4 支持pivot行转列

前言 lightdb-x从23.4版本支持pivot行转列功能&#xff1b;先了解oracle支持行转列功能&#xff1a; 语法如下&#xff1a; oracle描述如下&#xff1a; Oracle 11g introduced the new PIVOT clause that allows you to write cross-tabulation queries which transpose …

【数据结构】复习题(一)

一、选择题 1.组成数据的基本单位是()。 A. 数据项 B.数据类型 C.数据元素 D.数据变量 2.设数据结构A{D,R},其中D&#xff5b;1,2,3,4},R{r},r{<1,2>,<2,3>,< 3,4>,<4,1>}&#xff0c;则数据结构A是()。 A.线性结构 B.树型结构 C.图型结构 D.集合 3.…

DC电源模块的设计与制造技术创新

BOSHIDA DC电源模块的设计与制造技术创新 DC电源模块的设计与制造技术创新主要涉及以下几个方面&#xff1a; 1. 高效率设计&#xff1a;传统的DC电源模块存在能量转换损耗较大的问题&#xff0c;技术创新可通过采用高效率的电路拓扑结构、使用高性能的功率开关器件和优化控制…

【深度学习目标检测】四、基于深度学习的抽烟识别(python,yolov8)

YOLOv8是一种物体检测算法&#xff0c;是YOLO系列算法的最新版本。 YOLO&#xff08;You Only Look Once&#xff09;是一种实时物体检测算法&#xff0c;其优势在于快速且准确的检测结果。YOLOv8在之前的版本基础上进行了一系列改进和优化&#xff0c;提高了检测速度和准确性。…

人生感悟 | 当前经济形势,给25~35岁的年轻人一点建议

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 这两年经济情况怎么样呢&#xff1f;相信大家都有自己的感觉。 且不说网上看到的“裁员裁到大动脉”“设计院欠薪”等各种新闻。 说自己和家人的亲身经历吧&#xff0c;这两年经历了被拖欠工资、公司缩编、换工作、公…

python分析数据出现Text input context does not respond to _valueForTIProperty错误

一开始运行脚本还是不报错的&#xff0c;脚本内容部分如下&#xff1a; 出现了如下的效果图&#xff1a; 后面隔了几天再次运行居然报错了&#xff0c;如下图所示&#xff0c;但是也没有更改代码啊。后来发现原来是输入法导致的&#xff0c;把输入法切换成英文状态就不报错啦。…

gitlab 通过svn hook 触发

jenkins 起一个item 配置&#xff1a; 我选的自由风格的 源码管理配置 先选subversion 就是svn类型 url 设置project 的路径&#xff0c; 注意是工程&#xff0c;不是svn 顶层 添加一个账户来进行pull 等操作 选择添加的账号 构建触发器&#xff1a; &#xff0c;重要的是要自…

海安行车记录仪avi杀病毒导致文件丢失的恢复案例

海安行车记录仪&#xff0c;听名字就知道是个小小小品牌&#xff0c;而且用的文件格式是比较古老的AVI&#xff0c;这种文件格式是微软设计的&#xff0c;后来并没有普及&#xff08;不支持4G以上大文件而且结构过于松散&#xff09;。这个恢复案例比较特殊的地方是不太清楚做过…

matlab面向对象编程入门笔记

文章目录 1. 类和结构2. 定义类3. 属性3.1 private/protected/public属性3.2 constant属性3.3 hidden属性 4. 方法4.1 private/protected/public方法4.2 static方法4.3 外部方法 5. 动态调用6. 继承-超类6.1 handle超类6.2 dynamicprops 和 hgsetget子类 7. 封闭(sealed)类、方…

gitee gihub上传步骤

上传 1. 到具体要上传的文件目录 2. 右击git Bash Here 初始化仓库&#xff1a;git init 3. 添加文件 添加所有文件 : git add . &#xff08;注意这里有个点&#xff09;添加具体文件&#xff1a; git add test.md 4. 添加到暂存区 git commit -m 暂存区 5. 将本地代…