微软 C++编程风格指南
阅读原文时间:2021年04月26日阅读:1

编者按:本文翻译自微软的官方github库
https://github.com/Microsoft/AirSim/blob/master/docs/coding_guidelines.md

现代C ++编码指南

我们正在使用现代 C ++ 11。其中的智能指针,Lambdas和C ++ 11多线程原语将会是你的朋友。

Quick Note

“标准化”的好处是有很多可供选择标准: ISO, Sutter & Stroustrup, ROS, LINUX, Google, Microsoft, CERN, GCC, ARM, LLVM可能还有成千上万的代码标准。不幸的是,这些标准中的大多数甚至不能对类或常量的命名这样的基础内容达成一致。可能是因为这些标准需要支持已有代码库,所以经常带来许多遗留问题。本文的目的是创建与 ISO, Sutter & Stroustrup, ROS, LINUX保持一致的指南,同时解决尽可能多的冲突,缺点和不一致的问题。

命名约定

避免在命名上使用任何匈牙利表示法和在指针命名上使用_ptr

代码元素

样式

内容

Namespace

under_scored

Differentiate from class names

Class name

CamelCase

To differentiate from STL types which ISO recommends (do not use “C” or “T” prefixes)

Function name

camelCase

Lower case start is almost universal except for .Net world

Parameters/Locals

under_scored

Vast majority of standards recommends this because _ is more readable to C++ crowd (although not much to Java/.Net crowd)

Member variables

under_scored_with_

The prefix _ is heavily discouraged as ISO has rules around reserving _identifiers, so we recommend suffix instead

Enums and its members

CamelCase

Most except very old standards agree with this one

Globals

g_under_scored

You shouldn’t have these in first place!

Constants

UPPER_CASE

Very contentious and we just have to pick one here, unless if is a private constant in class or method, then use naming for Members or Locals

File names

Match case of class name in file

Lot of pro and cons either way but this removes inconsistency in auto generated code (important for ROS)

头文件

可以使用命名空间限定的#ifdef来防止多次inclusion:

#ifndef msr_airsim_MyHeader_hpp
#define msr_airsim_MyHeader_hpp

//--your code

#endif

我们不使用#pragma一次的原因是因为如果在多个位置存在相同的头文件(在ROS构建系统下可能会这样做),就不会支持它。

代码包围结构

内部函数或方法体将大括号放在同一行上。在命名空间,类和方法级别之外使用单独的行。这被称为K&R风格,其变体广泛用于C ++与其他语言中更受欢迎的其他风格。请注意,如果您有单个语句,则不需要花括号,但是复杂语句使用大括号能更容易保持正确。

int main(int argc, char* argv[])
{
     while (x == y) {
        f0();
        if (cont()) {
            f1();
        } else {
            f2();
            f3();
        }
        if (x > 100)
            break;
    }
}

Const和References

审查您声明为const和引用的候选者的所有非标量参数。如果您来自C#/ Java / Python等语言,那么您经常会犯的错误是按值传递参数而不是const T&;特别是您希望传递的大多数字符串,向量和地图const T&;(如果它们是只读的)或者T&(如果它们是可写的)。还要const尽可能地为方法添加后缀。

重写

覆盖虚拟方法时,请使用覆盖后缀。

指针

这真的是关于内存管理。模拟器有很多性能关键代码,因此我们尝试避免因大量调用new / delete而使内存管理器过载。我们还希望避免在堆栈上过多地复制内容,因此我们尽可能通过引用传递内容。但是当对象真的需要比调用堆栈更长寿时,你经常需要在堆上分配该对象,因此你有一个指针。现在,如果管理该对象的生命周期变得棘手,我们建议使用 C ++ 11智能指针。但智能指针确实有成本,所以不要盲目地随处使用它们。对于性能至关重要的私有代码,可以使用原始指针。当与仅接受指针类型的遗留系统(例如,套接字API)接口时,通常还需要原始指针。但我们尝试尽可能地包装这些遗留接口,并避免这种编程风格泄漏到更大的代码库中。

例如,检查你是否可以在任何地方使用const const float * const xP。避免使用前缀或后缀来指示变量名中的指针类型,即使用my_obj而不是myobj_ptr在可能更好地区分变量的情况下使用,例如,int mynum = 5; int* mynum_ptr = mynum;

是不是太短了?

是的,作者是故意的,因为没有人喜欢阅读200页编码指南。本文的目标是仅涵盖GCC中的严格编译模式和VC ++中的4级警告&错误未涵盖的最重要的事情。如果你想知道如何用C ++编写更好的代码,请参阅GotWEffective Modern C ++一书。