关键词:
本系列是开源书C++ Best Practises[1]的中文版,全书从工具、代码风格、安全性、可维护性、可移植性、多线程、性能、正确性等角度全面介绍了现代C++项目的最佳实践。本文是该系列的第三篇。
C++最佳实践:
3. 安全性(本文)
4. 可维护性
5. 可移植性及多线程
6. 性能
7. 正确性和脚本
安全性
尽量使用const
用const
修饰变量或方法,从而告诉编译器这些都是不可变的,有助于编译器优化代码,并帮助开发人员了解函数是否有副作用。此外,使用const &
可以防止编译器复制不必要的数据。John Carmack对```const```的评论[2]值得一读。
// Bad Idea
class MyClass
public:
void do_something(int i);
void do_something(std::string str);
;
// Good Idea
class MyClass
public:
void do_something(const int i);
void do_something(const std::string &str);
;
仔细考虑返回类型
Getters(成员变量读取API)
正常情况下,通过返回值读取成员变量时,使用
&
或const &
返回值可以显著提高性能按值返回更有利于线程安全,如果返回的值就是为了复制使用,就不会有性能损耗
如果API返回值使用协变类型(covariant return types),必须返回
&
或*
临时值和局部值
始终按值返回
参考:
https://github.com/lefticus/cppbestpractices/issues/21
https://twitter.com/lefticus/status/635943577328095232
不要用const引用传递和返回简单类型
// Very Bad Idea
class MyClass
public:
explicit MyClass(const int& t_int_value)
: m_int_value(t_int_value)
const int& get_int_value() const
return m_int_value;
private:
int m_int_value;
相反,通过值传递和返回简单类型。如果不打算更改传递的值,请将它们声明为const
,但不要声明为const
引用:
// Good Idea
class MyClass
public:
explicit MyClass(const int t_int_value)
: m_int_value(t_int_value)
int get_int_value() const
return m_int_value;
private:
int m_int_value;
为什么要这样?因为通过引用传递和返回会导致指针操作,而值传递在处理器寄存器中处理,速度更快。
避免访问裸内存
C++中很难在没有内存错误和泄漏风险[3]的情况下正确处理裸内存的访问、分配和回收,C++11提供了避免这些问题的工具。
// Bad Idea
MyClass *myobj = new MyClass;
// ...
delete myobj;
// Good Idea
auto myobj = std::make_unique<MyClass>(constructor_param1, constructor_param2); // C++14
auto myobj = std::unique_ptr<MyClass>(new MyClass(constructor_param1, constructor_param2)); // C++11
auto mybuffer = std::make_unique<char[]>(length); // C++14
auto mybuffer = std::unique_ptr<char[]>(new char[length]); // C++11
// or for reference counted objects
auto myobj = std::make_shared<MyClass>();
// ...
// myobj is automatically freed for you whenever it is no longer used.
用std::array
或std::vector
代替C风格的数组
这两种方法都保证了对象的连续内存布局,并且可以(而且应该)完全取代C风格数组,另外这也是不使用裸指针的诸多原因之一。
另外,避免使用```std::shared_ptr```保存数组[4]。
使用异常
返回值(例如boost::optional
),可以被忽略,如果不检查,可能会导致崩溃或内存错误,而异常不能被忽略。另一方面,异常可以被捕获和处理。可能异常会一直上升到应用程序的最高层级被捕获、记录到日志中,并触发应用自动重启。
C++的设计者之一Stroustrup谈论过这个话题: Why use exceptions?[5]
用C++风格的类型转换,而不是C风格的类型转换
用C++风格的强制类型转换(static_cast<>
,dynamic_cast<>
,…)代替C风格的强制类型转换,C++风格的强制转换允许更多的编译器检查,而且相当安全。
// Bad Idea
double x = getX();
int i = (int) x;
// Not a Bad Idea
int i = static_cast<int>(x);
此外,C++类型转换风格更为显式,对搜索更为友好。
但如果需要将double
类型转换为int
类型,请考虑重构程序逻辑(例如,对溢出和下溢进行额外检查)。避免出现测量了3次,然后切割0.9999999999981次这种情况。
不要定义可变参数函数(variadic function)
可变参数函数可以接受数量可变的参数,最著名的例子可能是printf()
。虽然可以定义此类函数,但可能存在安全风险。可变参数函数的使用不是类型安全的,错误的输入参数可能导致程序以未定义的行为终止。这种未定义的行为可能会导致安全问题。如果使用支持C++1的编译器,那么可以使用可变参数模板。
参考: It is technically possible to make typesafe C-style variadic functions with some compilers[6]
额外资源
David Wheeler的《How to Prevent The Next Heartbleed[7]》一书很好的分析了代码安全的现状以及如何确保代码安全。
微信公众号:DeepNoMind
参考资料
[1]
C++ Best Practises: https://lefticus.gitbooks.io/cpp-best-practices/content/
[2]John Carmack对const
的评论: http://kotaku.com/454293019
内存错误和泄漏风险: http://blog2.emptycrate.com/content/nobody-understands-c-part-6-are-you-still-using-pointers
[4]避免使用std::shared_ptr
保存数组: http://stackoverflow.com/questions/3266443/can-you-use-a-shared-ptr-for-raii-of-c-style-arrays
Why use exceptions?: https://www.stroustrup.com/bs_faq2.html#exceptions-why
[6]It is technically possible to make typesafe C-style variadic functions with some compilers: https://github.com/lefticus/cppbestpractices/issues/53
[7]How to Prevent The Next Heartbleed: http://www.dwheeler.com/essays/heartbleed.html
- END -点击阅读原文加入知识星球
c++最佳实践|1.工具(代码片段)
...;+BestPractises[1]的中文版,全书从工具、代码风格、安全性、可维护性、可移植性、多线程、性能、正确性等角度全面介绍了现代C++项目的最佳实践。本文是该系列的第一篇。C++最佳实践:1.工具(本文)2... 查看详情
c++最佳实践|1.工具(代码片段)
...;+BestPractises[1]的中文版,全书从工具、代码风格、安全性、可维护性、可移植性、多线程、性能、正确性等角度全面介绍了现代C++项目的最佳实践。本文是该系列的第一篇。C++最佳实践:1.工具(本文)2... 查看详情
c++最佳实践|2.代码风格(代码片段)
...;+BestPractises[1]的中文版,全书从工具、代码风格、安全性、可维护性、可移植性、多线程、性能、正确性等角度全面介绍了现代C++项目的最佳实践。本文是该系列的第二篇。C++最佳实践:1.工具2.代码风格(... 查看详情
c++最佳实践|2.代码风格(代码片段)
...;+BestPractises[1]的中文版,全书从工具、代码风格、安全性、可维护性、可移植性、多线程、性能、正确性等角度全面介绍了现代C++项目的最佳实践。本文是该系列的第二篇。C++最佳实践:1.工具2.代码风格(... 查看详情
c++最佳实践|4.可维护性(代码片段)
...;+BestPractises[1]的中文版,全书从工具、代码风格、安全性、可维护性、可移植性、多线程、性能、正确性等角度全面介绍了现代C++项目的最佳实践。本文是该系列的第四篇。C++最佳实践:1.工具2.代码风格3. 安... 查看详情
c++最佳实践|3.安全性(代码片段)
...;+BestPractises[1]的中文版,全书从工具、代码风格、安全性、可维护性、可移植性、多线程、性能、正确性等角度全面介绍了现代C++项目的最佳实践。本文是该系列的第三篇。C++最佳实践:1.工具2.代码风格3. 安... 查看详情
c++最佳实践|3.安全性(代码片段)
...;+BestPractises[1]的中文版,全书从工具、代码风格、安全性、可维护性、可移植性、多线程、性能、正确性等角度全面介绍了现代C++项目的最佳实践。本文是该系列的第三篇。C++最佳实践:1.工具2.代码风格3. 安... 查看详情
c++最佳实践|5.可移植性及多线程(代码片段)
...;+BestPractises[1]的中文版,全书从工具、代码风格、安全性、可维护性、可移植性、多线程、性能、正确性等角度全面介绍了现代C++项目的最佳实践。本文是该系列的第五篇。C++最佳实践:1.工具2.代码风格3. 安... 查看详情
c++最佳实践|5.可移植性及多线程(代码片段)
...;+BestPractises[1]的中文版,全书从工具、代码风格、安全性、可维护性、可移植性、多线程、性能、正确性等角度全面介绍了现代C++项目的最佳实践。本文是该系列的第五篇。C++最佳实践:1.工具2.代码风格3. 安... 查看详情
html网络安全最佳实践(代码片段)
制作容器镜像的最佳实践(代码片段)
...保证镜像是可复用的,提升DevOps效率,另一方面是为了提高安全性.希望对各位有所帮助.本文分为四部分内容,分别是:通用容器镜像最佳实践Java容器镜像最佳实践NGINX容器镜像最佳实践以及Python容器最 查看详情
框架设计(代码片段)
...安全事件的响应。2。架构良好的框架包括四个用于云中安全性的区域:数据保护,基础结构保护,特权管理和缺陷控制。什么是架构良好的框架?1.数据保护。2.基础结构保3.特权管理4.缺陷控制。3.以下哪项可用于检测或识别AWS... 查看详情
web安全头号大敌xss漏洞解决最佳实践(代码片段)
XSSXSS代码攻击及危害分析——><script快速创建springboot应用: <groupId>org.owasp.antisamy</groupId> <artifactId>antisamy</artifactId&g 查看详情
kafka集群监控安全机制与最佳实践(代码片段)
Kafka监控安装Kafka集群监控方案选择:Kafka只能依靠kafka-run-class.sh等命令进行管理KafkaManager(CMAK)是目前比较常用的监控工具,它有如下功能:管理多个集群轻松检查群集状态(主题,消费者,偏移,代理,副本分发,分区分发... 查看详情
是否有在 C++ 中循环“一直通过”数组的最佳实践?
】是否有在C++中循环“一直通过”数组的最佳实践?【英文标题】:Isthereabest-practiceforlooping"allthewaythrough"anarrayinC++?【发布时间】:2014-07-2421:58:38【问题描述】:在Python中,可以使用以下代码将数组的每个元素与“下一个... 查看详情
spring事务使用最佳实践(代码片段)
目录1Spring事务最佳实践1.1、Spring事务传播机制1.2、隔离规则1.3、Spring事务实现方式1.3.1、编程式事务实现1.3.2、声明式事务实现1.3.3、Spring声明式事务使用注意事项2、事务问题治理2.1、大事物的危害2.1.1事务问题原因分类2.1.2、大... 查看详情
eos智能合约开发最佳实践(代码片段)
安全问题1.可能的错误智能合约终止限制转账限额限制速率有效途径来进行bug修复和提升2.谨慎发布智能合约对智能合约进行彻底的测试并在任何新的攻击手法被发现后及时制止赏金计划和审计合约3.合约的简介确保智能合约逻辑... 查看详情
21条最佳实践,全面保障github使用安全(代码片段)
GitHub是开发人员工作流程中不可或缺的一部分。无论你去哪个企业或开发团队,GitHub都以某种形式存在。它被超过8300万开发人员,400万个组织和托管超过2亿个存储库使用。GitHub是世界上最大的源代码托管服务平台。 GitHub... 查看详情