Google C++编程风格指南(二)

飞牛 NAS 部署 Hermes Agent 全指南:打造 24 小时在线、自我进化的 AI 智能体! 当大多数人还在把 AI 当聊天机器人使用时,我已经把它部署到了家里的飞牛 NAS 上,让它 24 小时在线工作、记忆我的习惯、自动执行任务,甚至还能不断学习新的技能。今天带你从零搭建这个真正属于自己的 AI Agent。🚀 阅读详情

原文地址:Google C++ Style Guide

  • 作用域

1. 命名空间(Namespaces)

在.cc文件中,提倡使用不具名的命名空间(unnamed namespaces,译者注:不具名的命名空间就像不具名的类一样,似乎被介绍的很少:-()。使用具名命名空间时,其名称可基于项目或路径名称,不要使用using指示符。

定义:命名空间将全局作用域细分为不同的、具名的作用域,可有效防止全局作用域的命名冲突。

优点:命名空间提供了(可嵌套)命名轴线(name axis,译者注:将命名分割在不同命名空间内),当然,类也提供了(可嵌套)的命名轴线(译者注:将命名分割在不同类的作用域内)。

举例来说,两个不同项目的全局作用域都有一个类Foo,这样在编译或运行时造成冲突。如果每个项目将代码置于不同命名空间中,project1::Foo和project2::Foo作为不同符号自然不会冲突。

缺点:命名空间具有迷惑性,因为它们和类一样提供了额外的(可嵌套的)命名轴线。在头文件中使用不具名的空间容易违背C++的唯一定义原则(One Definition Rule (ODR))。

结论:根据下文将要提到的策略合理使用命名空间。

1) 不具名命名空间(Unnamed Namespaces)

在.cc文件中,允许甚至提倡使用不具名命名空间,以避免运行时的命名冲突:

namespace {                                   // .cc 文件中

// 命名空间的内容无需缩进
enum { UNUSED, EOF, ERROR };          // 经常使用的符号
bool AtEof() { return pos_ == EOF; }   // 使用本命名空间内的符号EOF

}  // namespace

然而,与特定类关联的文件作用域声明在该类中被声明为类型、静态数据成员或静态成员函数,而不是不具名命名空间的成员。像上文展示的那样,不具名命名空间结束时用注释// namespace标识。

不能在.h文件中使用不具名命名空间。

2) 具名命名空间(Named Namespaces)

具名命名空间使用方式如下:

命名空间将除文件包含、全局标识的声明/定义以及类的前置声明外的整个源文件封装起来,以同其他命名空间相区分。

// .h文件
namespace mynamespace {

// 所有声明都置于命名空间中
// 注意不要使用缩进
class MyClass {
public:
  ...
  void Foo();
};

}  // namespace mynamespace

// .cc文件
namespace mynamespace {

// 函数定义都置于命名空间中
void MyClass::Foo() {
  ...
}

}  // namespace mynamespace

通常的.cc文件会包含更多、更复杂的细节,包括对其他命名空间中类的引用等。

#include "a.h"

DEFINE_bool(someflag, false, "dummy flag");

class C;  // 全局命名空间中类C的前置声明
namespace a { class A; }  // 命名空间a中的类a::A的前置声明

namespace b {

...code for b...                // b中的代码

}  // namespace b

不要声明命名空间std下的任何内容,包括标准库类的前置声明。声明std下的实体会导致不明确的行为,如,不可移植。声明标准库下的实体,需要包含对应的头文件。

最好不要使用using指示符,以保证命名空间下的所有名称都可以正常使用。

// 禁止——污染命名空间
using namespace foo;

在.cc文件、.h文件的函数、方法或类中,可以使用using。

// 允许:.cc文件中
// .h文件中,必须在函数、方法或类的内部使用
using ::foo::bar;

在.cc文件、.h文件的函数、方法或类中,还可以使用命名空间别名。

// 允许:.cc文件中
// .h文件中,必须在函数、方法或类的内部使用

namespace fbz = ::foo::bar::baz;

2. 嵌套类(Nested Class)

当公开嵌套类作为接口的一部分时,虽然可以直接将他们保持在全局作用域中,但将嵌套类的声明置于命名空间中是更好的选择。

定义:可以在一个类中定义另一个类,嵌套类也称成员类(member class)。

class Foo {

private:
  // Bar是嵌套在Foo中的成员类
  class Bar {
    ...
  };

};

优点:当嵌套(成员)类只在被嵌套类(enclosing class)中使用时很有用,将其置于被嵌套类作用域作为被嵌套类的成员不会污染其他作用域同名类。可在被嵌套类中前置声明嵌套类,在.cc文件中定义嵌套类,避免在被嵌套类中包含嵌套类的定义,因为嵌套类的定义通常只与实现相关。

缺点:只能在被嵌套类的定义中才能前置声明嵌套类。因此,任何使用Foo::Bar*指针的头文件必须包含整个Foo的声明。

结论:不要将嵌套类定义为public,除非它们是接口的一部分,比如,某个方法使用了这个类的一系列选项。

3. 非成员函数(Nonmember)、静态成员函数(Static Member)和全局函数(Global Functions)

使用命名空间中的非成员函数或静态成员函数,尽量不要使用全局函数。

优点:某些情况下,非成员函数和静态成员函数是非常有用的,将非成员函数置于命名空间中可避免对全局作用域的污染。

缺点:将非成员函数和静态成员函数作为新类的成员或许更有意义,当它们需要访问外部资源或具有重要依赖时更是如此。

结论:

有时,不把函数限定在类的实体中是有益的,甚至需要这么做,要么作为静态成员,要么作为非成员函数。非成员函数不应依赖于外部变量,并尽量置于某个命名空间中。相比单纯为了封装若干不共享任何静态数据的静态成员函数而创建类,不如使用命名空间。

定义于同一编译单元的函数,被其他编译单元直接调用可能会引入不必要的耦合和连接依赖;静态成员函数对此尤其敏感。可以考虑提取到新类中,或者将函数置于独立库的命名空间中。

如果你确实需要定义非成员函数,又只是在.cc文件中使用它,可使用不具名命名空间或static关联(如static int Foo() {...})限定其作用域。

4. 局部变量(Local Variables)

将函数变量尽可能置于最小作用域内,在声明变量时将其初始化。

C++允许在函数的任何位置声明变量。我们提倡在尽可能小的作用域中声明变量,离第一次使用越近越好。这使得代码易于阅读,易于定位变量的声明位置、变量类型和初始值。特别是,应使用初始化代替声明+赋值的方式。

int i;
i = f();        // 坏——初始化和声明分离
nt j = g();   // 好——初始化时声明

注意:gcc可正确执行for (int i = 0; i < 10; ++i)(i的作用域仅限for循环),因此其他for循环中可重用i。if和while等语句中,作用域声明(scope declaration)同样是正确的。

while (const char* p = strchr(str, '/')) str = p + 1;

注意:如果变量是一个对象,每次进入作用域都要调用其构造函数,每次退出作用域都要调用其析构函数。

// 低效的实现
for (int i = 0; i < 1000000; ++i) {
  Foo f;  // 构造函数和析构函数分别调用1000000次!
  f.DoSomething(i);
}

类似变量放到循环作用域外面声明要高效的多:

Foo f;  // 构造函数和析构函数只调用1次
for (int i = 0; i < 1000000; ++i) {
  f.DoSomething(i);
}

5. 全局变量(Global Variables)

class类型的全局变量是被禁止的,内建类型的全局变量是允许的,当然多线程代码中非常数全局变量也是被禁止的。永远不要使用函数返回值初始化全局变量。

不幸的是,全局变量的构造函数、析构函数以及初始化操作的调用顺序只是被部分规定,每次生成有可能会有变化,从而导致难以发现的bugs。

因此,禁止使用class类型的全局变量(包括STL的string, vector等等),因为它们的初始化顺序有可能导致构造出现问题。内建类型和由内建类型构成的没有构造函数的结构体可以使用,如果你一定要使用class类型的全局变量,请使用单件模式(singleton pattern)。

对于全局的字符串常量,使用C风格的字符串,而不要使用STL的字符串:

const char kFrogSays[] = "ribbet";

虽然允许在全局作用域中使用全局变量,使用时务必三思。大多数全局变量应该是类的静态数据成员,或者当其只在.cc文件中使用时,将其定义到不具名命名空间中,或者使用静态关联以限制变量的作用域。

记住,静态成员变量视作全局变量,所以,也不能是class类型!

______________________________________

译者:这一篇主要提到的是作用域的一些规则,总结一下:

1. .cc中的不具名命名空间可避免命名冲突、限定作用域,避免直接使用using提示符污染命名空间;

2. 嵌套类符合局部使用原则,只是不能在其他头文件中前置声明,尽量不要public;

3. 尽量不用全局函数和全局变量,考虑作用域和命名空间限制,尽量单独形成编译单元;

4. 多线程中的全局变量(含静态成员变量)不要使用class类型(含STL容器),避免不明确行为导致的bugs。

作用域的使用,除了考虑名称污染、可读性之外,主要是为降低耦合度,提高编译、执行效率。

YOLOv5源码逐行超详细注释与解读(5)——配置文件yolov5s.yaml 全网最详细的YOLOv5源码解读之配置文件yaml。逐行注释,逐句讲解,一文带你了解yaml。小白必看! 阅读详情

相关推荐

Hi3516CV610硬件设计避坑指南:从电源模块到DDR布线实战解析

本文深入解析了Hi3516CV610硬件设计中的关键难点与实战技巧。重点剖析了电源架构的选型陷阱与PCB布局要点,详细阐述了DDR3/L高速布线的等长匹配、信号完整性及端接策略,并提供了MIPI接口与时钟电路的隔离设计指南。旨在帮助工程师规避常见设计错误,提升系统稳定性与可靠性。

ooo22的博客 255

不具名的命名空间(unnamed namespaces)

众所周知,命名空间是用来防止对象的重复定义的。 如下,编译不会出错:namespace n1 { int x; } namespace n2 { int x; } //访问 n1.x; n2.x;上面是具名的名字空间,不具名的名字空间也是防止对象重复定义用,只是他没有名字而已。file1.cpp: namespace { //变量x和方法fun只在file1.cpp可见

混沌的博客 5604

数字化转型是什么?核心又是什么呢?

01到底什么是数字化转型? 这时候你或许要问笔者了,既然你说使用新兴技术不是数字化转型,那使用新的商业模式总该是数字化转型了吧?你比如阿里巴巴,作为我们中国人最熟悉的开展电子商务的公司,它可以说是新的商业模式最大的开创者了:阿里巴巴是世界上最大的零售商,却没有任何一家实体店和任何库存;再比如优步(Uber),我们非常熟悉的一个线上打车平台,它可以算是世界上最大的出租车公司了,但是它不拥有一辆出租车。还有近些年来,我们经常使用的的旅游房屋租赁社区爱彼迎(Airbnb),它可以为消费者提供多样的住宿信息..

weixin_58342023的博客 4043

namespace 没有名字_C++基础入门知识:C++命名空间(名字空间)详解

一个中大型软件往往由多名程序员共同开发,会使用大量的变量和函数,不可避免地会出现变量或函数的命名冲突。当所有人的代码都测试通过,没有问题时,将它们结合到一起就有可能会出现命名冲突。例如小李和小韩都参与了一个文件管理系统的开发,它们都定义了一个全局变量 fp,用来指明当前打开的文件,将他们的代码整合在一起编译时,很明显编译器会提示 fp 重复定义(Redefinition)错误。为了解决合作开发时的...

weixin_39653481的博客 889

u3d逆向学习之纯C内存读写与ImGui绘制(Android)

方法:需要在/proc/pid/maps文件查找模块名,一行行遍历所有内存,第一个参数为模块名,第二个参数为索引index(因为该模块会有多个,index为正序遍历第index个该模块),若找到了则使用。32位游戏的指针大小采用4字节,而64位游戏的指针大小采用8字节(这里需要注意),数据地址以16进制存储,使用unsigned long类型 ,该函数只有一个参数,数据地址,返回该地址的指针跳转地址。文件,比较其中的内容是否与传入的包名相同,如果相同,则返回该进程的PID。

zhoujunjie2004的博客 1687

SC-FDMA

<br />SC-FDMA(Single-carrier Frequency-Division Multiple Access,單載波分頻多工),是LTE的上行鏈路的主流多址。<br />SC-FDMA是單波載(Single-carrier),與OFDMA相比之下具有的較低的PAPR(峰值/平均功率比,peak-to-average power ratio),比多載波的PAPR低1-3dB左右(PAPR是由于多載波在频域叠加引起)。更低的PAPR可以使行動終端(mobile terminal)在發送功效方面

jod的专栏 3299

头文件包含问题

一、类嵌套的疑问C++头文件重复包含实在是一个令人头痛的问题,前一段时间在做一个简单的数据结构演示程序的时候,不只一次的遇到这种问题。假设我们有两个类A和B,分别定义在各自的有文件A.h和B.h中,但是在A中要用到B,B中也要用到A,但是这样的写法当然是错误的:class B;class A{      public:          B b;};class B{

meteor2520的专栏 3825

WRF后处理避坑指南:从namelist配置到降水计算的全流程解析

本文提供了一份详尽的WRF模式后处理避坑指南,涵盖从理解wrfout文件结构、核心变量解析到累计降水计算与专业气象图绘制的全流程。重点解析了RAINC与RAINNC的正确处理方法,并分享了使用wrf-python库高效绘制位势高度叠加风场图、累计降水图等专业图表的实战技巧与代码,旨在帮助用户规避常见错误,提升后处理效率与图表质量。

weixin_29200485的博客 353

C++全局对象的初始化顺序问题思考

问题产生: 在代码中的某个头文件定了几个全局的 const std::string ,同时定义了某个类,在类的构造函数中使用了这几个全局变量。 该类作为单例模板的成员被使用了,单例的编译在另外一个单元。 程序编译链接正常,运行时候segment fault gdb调试const 成员变量,内存不可访问 分析该问题需要具备的基础知识: 知识一: 全局变量、文件域的静态变量和类的静态...

veghlreywg的博客 2046

Fofa API高阶玩法:用Python批量获取漏洞资产(含OA系统扫描实战)

本文详细介绍了如何利用Python结合Fofa API实现自动化漏洞资产收集的高阶实战技巧。通过构建健壮的客户端、设计精准查询语法、实现多线程批量采集,并以OA系统漏洞扫描为例,演示了从资产发现、过滤验证到报告生成的全流程,旨在提升安全运维与应急响应的效率。

weixin_28607671的博客 497

从Chiplet到UCIE:D2D互联技术如何重塑半导体设计生态

本文探讨了D2D互联技术在半导体设计中的革命性作用,从Chiplet到UCIE标准的演进如何重塑行业生态。详细分析了D2D互联的技术本质、架构选择及UCIE标准带来的变革,并展望了未来光学D2D和3D集成等趋势。高速互联接口技术的突破为AI加速器和计算芯片提供了更高带宽和能效。

weixin_29292535的博客 931

Google C++编程风格指南(二):作用域

1. .cc中的不具名命名空间可避免命名冲突、限定作用域,避免直接使用using提示符污染命名空间; 2.嵌套类符合局部使用原则,只是不能在其他头文件中前置声明,尽量不要public;3.尽量不用全局函数和全局变量,考虑作用域和命名空间限制,尽量单独形成编译单元…… 作用域1. 命名空间(Namespaces)在.cc文件中,提倡使用不具名的命名空间(unnam

周睿的博客(blog) 1066

使用 MATLAB/Simulink 构建一个基于PID控制的直流电机速度调节系统模型

直流电机(DC Motor)因其结构简单、成本低廉、易于控制等特点,广泛应用于各种工业自动化和家用电器中。PID控制器作为最常用的控制策略之一,在直流电机的速度调节系统中具有重要应用价值。通过合理调整比例(P)、积分(I)、微分(D)三个参数,可以实现对电机速度的精确控制。本教程将带你使用构建一个基于PID控制的直流电机速度调节系统模型,涵盖电机模型构建、PID控制器设计、系统仿真与调试等多个方面。本文介绍了如何使用构建一个基于PID控制的直流电机速度调节系统模型。

amy_mhd的博客 217

[译]Google C++编程风格指南(二)

原文地址:Google C++ Style Guide 作用域 1. 命名空间(Namespaces) 在.cc文件中,提倡使用不具名的命名空间(unnamed namespaces,译者注:不具名的命名空间就像不具名的类一样,似乎被介绍的很少:-()。使用具名命名空间时,其名称可基于项目或路径名称,不要使用using指示符。 定义:命名空间将全局作用域细分为不同的、具

ziyou飞翔的专栏 518

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

(转)[译]Google C++编程风格指南(二)

 作用域1. 命名空间(Namespaces)在.cc文件中,提倡使用不具名的命名空间(unnamed namespaces,译者注:不具名的命名空间就像不具名的类一样,似乎被介绍的很少:-()。使用具名命名空间时,其名称可基于项目或路径名称,不要使用using指示符。定义:命名空间将全局作用域细分为不同的、具名的作用域,可有效防止全局作用域的命名冲突。优点:命名空间提

wlzt123的专栏 506

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Google C++编程风格指南(二):作用域(转载)

作用域<br />1. 命名空间(Namespaces)<br />在.cc文件中,提倡使用不具名的命名空间(unnamed namespaces,译者注:不具名的命名空间就像不具名的类一样,似乎被介绍的很少:-()。使用具名命名空间时,其名称可基于项目或路径名称,不要使用using指示符。<br />定义: 命名空间将全局作用域细分为不同的、具名的作用域,可有效防止全局作用域的命名冲突。<br />优点: 命名空间提供了(可嵌套)命名轴线(name axis,译者注:将命名分割在不同命名空间内),当然

wulong710的专栏 582

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Google C++ 开源风格指南

Google 在 C++ 编程中的代码风格规范、命名约定、注释要求和格式规定,提升代码的可读性、可维护性和规范性。

有耐心做好简单事情,坚持写blog 4193

Google 编程风格:C++、Python、JavaScript、Shell、TypeScript

Google 编程风格:C++、Python、JavaScript、Shell、TypeScript

freeking101的博客 5万+

c++ google编程风格

简介 编码不易,每家公司都有它的脾气。 c++的编码风格也有不少流派,这里独选google,一是因为它牛逼,向牛逼的学习总没错,二是它有很多开源项目使用的就是这个风格。 当你不知道怎么做才好时,就先用google的吧,已经有无数前仁验证过了。 本文不是要再罗列一遍所有的细则,而是提炼出编码中随时需要使用的部分,作出总结,这样方便参考。 具体结节,还请稳步开源文档:C++ 风格指南。 头文件 使用 #define 保护,为保证唯一性,头文件的命名使用项目目录的全路径 避免使用前置声明,使用 #inclu

guotianqing的博客 1388

Google C++编程风格指南

  [译]Google C++编程风格指南(八)[完] 2008年09月03日 星期三 17:06 原文地址:Google C++ Style Guide 规则之例外前面说明的编码习惯基本是强制性的,但所有优秀的规则都允许例外。1. 现有不统一代码(Existing Non-conformant 阅读全文>> 类别:c

skyremember的专栏 1234

Google C++ 风格指南

背景介绍 风格指南的目标 C++ 版本 头文件 自包含头文件 #define 防护 包含所需内容 前置声明 在头文件中定义函数 头文件包含顺序与命名规范 作用域 命名空间 内部链接 非成员函数、静态成员函数与全局函数 局部变量 静态与全局变量 关于析构的决策 关于初始化的决策 常见模式 thread_local 变量 类 构造函数中的工作处理 隐式转换 可复制与可移动类型 优势 实现要点 注意事项 规范要求 结构体与类的选择 结构体 vs. 对组与元组 继承 运算符重载 访问控制 声明顺序 函数 输入与输出

AI工程化、开源分享、文档翻译、代码笔记 1443

Google C++ Style Guide - Google C++ 风格指南

Google C++ Style Guide - Google C++ 风格指南

程永强 2314

Google C++项目编程风格指南 (中文版) 分享

之前点击上方“AI算法与图像处理”,选择加"星标"或“置顶”重磅干货,第一时间送达导读这是一份来自Google开源的文档c++部分总共有 67 页,本文分享的内容,是基...

zero的博客 1575

Google C++ Style Guide 谷歌 C++编码风格指南,深入理解华为与谷歌的编程规范——C和C++实践指南

来看,return;(比如刷新 log),您可以把它绑定到 _at_quick_exit(). 如果您想在 exit() 和 quick_exit() 都用上该 handler, 都。Tip: 使用 C++ 的类型转换, 如 static_cast<>(). 不要使用 int y = (int)x 或 int y = int(x) 等转换方式;TextQuery::TextQuery(std::string word) : word_(word) {} , 其中 word_ 自然是类内私有成员。

C++,Java,Python,C#编程选手,偶尔刷刷leetcode 1388
上一篇: Google C++编程风格指南(一)
下一篇: Google C++编程风格指南(三)
olncy
博客等级 码龄20年 30粉丝 37原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值