[C++] 编程实践之1: Google的C++代码风格2:作用域

C++:C++代码风格指南--Google(未完待续) 所谓「前置声明」(forward declaration)是类、函数和模板的纯粹声明,没伴随着其定义. 阅读详情

作用域

名字空间

鼓励在.cc文件内使用匿名名字空间。使用具名的名字空间时,其名称可基于项目名或者相对路径。禁止使用using指示(using-directive)。禁止使用内联命名空间(inline namespace)。

定义:

  • 名字空间将全局作用域细分为独立的,具名的作用域,可有效防止全局作用域的命名冲突。

优点:

  • 虽然类已经提供了(可嵌套的)命名轴线,名字空间在这一基础上又做了一层封装。
  • 内联命名空间会自动把内部的标识符放到外层的作用域,比如下面的代码中,X::Y::foo()与X::foo()彼此可代替。内联命名空间主要用来保持跨版本的API的兼容性。
namespace X {
    inline namespace Y {
        void foo();
    }
}

缺点:

  • 名字空间具有迷惑性,因为它们和类一样提供了额外的(可嵌套的)命名轴线。此外,它们不再受其声明所在的命名空间的限制。
  • 内联命名空间只在大型版本控制里有用。
  • 在头文件中使用匿名空间导致违背C++的唯一定义原则(One Definition Rule (ODR))。

结论:

  • 根据下文将要提到的策略合理地使用命名空间。
匿名名字空间
  • 在.cc文件中,允许甚至鼓励使用匿名名字空间,以避免运行时的命名冲突。然而,与特定类关联的文件作用域声明在该类中被声明为类型、静态数据成员或者静态成员函数,而不是匿名名字空间的成员。匿名空间结束时用注释 //namespace标识。
namespace {                                  // .cc文件中
    // 名字空间的内容无需知道
    enum {kUNUSED, kEOF, kERROR};            // 经常使用的符号
    bool AtEof() { return pos == kEOF; }     // 使用本名字空间内的符号EOF
}   // namespace
  • 不要在.h文件中使用匿名名字空间。
具名名字空间

具名的名字空间使用方式如下:

  • 用名字空间把文件包含gflags的声明/定义,以及类的前置声明以外的整个源文件封装起来,以区别于其它名字空间:
// .h 文件
namespace mynamespace {
// 所有声明都置于命名空间中
// 注意不要使用缩进
class MyClass {
    public:
    ...
    void Foo();
};
}
// .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的前置声明
namespace b {
...code for b...            // b中的代码
} // namespace b
  • 不要在名字空间std内声明任何东西,包括标准库的类前置声明。在std名字空间声明实体会导致不确定的问题,比如不可移植。声明标准库下的实体,需要包括对应的头文件。
  • 最好不要使用using指示,以保证名字空间下的所有名称都可以正常使用。
  • 在.cc文件,.h文件的函数、方法或者类中,可以使用using声明。
// 允许.cc 文件中使用using声明
// 如果在.h文件中,必须在函数、方法或者类的内部使用
using ::foo::bar;
  • 在.cc文件,.h文件的函数、方法或者类中,允许使用名字空间别名。注意在.h文件的别名对包含了该头文件的所有人可见,所以在公共头文件(在项目外可用)以及它们递归包含的其它头文件里,不要用别名。毕竟原则上公共API要尽可能地精简。
// 允许:.cc文件中
// .h文件的话,必须在函数,方法或者类的内部使用
namespace fbz = ::foo::bar::baz;

// 在 .h文件里
namespace librarian {
// 以下别名在所有包含了该头文件的文件中生效。
namespace pd_s = ::pipeline_diagnostics::sidetable;

inline void my_inline_function() {
    // namespace alas local to a function (or method).
    namespace fbz = ::foo::bar::baz;
    ...
}
}   // namespace librarian
  • 禁止使用内联命名空间。

嵌套类

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

定义:

  • 一个类的内部定义另外一个类;嵌套类也被成为成员类(member class)。
class Foo {
private:
    // Bar是嵌套类Foo中的成员类
    class Bar {
        ...
    };
}

优点:

  • 当嵌套类只被外围类使用时非常有用;把它作为外围类作用域内的成员,而不是去污染外部作用域的同名类。嵌套类可以在外围类中做前置声明,然后在.cc文件中定义,这样避免在外围类的声明中定义嵌套类,因为嵌套类的定义通常只与实现相关。

缺点:

  • 嵌套类只能在外围类的内部做前置声明。因此,任何使用了Foo::Bar*的指针的头文件不得不包含类Foo的整个声明。

结论:

  • 不要讲嵌套类定义成为公有,除非它们是接口的一部分,比如嵌套类含有某些方法的一组选项。

非成员函数、静态成员函数和全局函数

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

优点:

  • 某些情况下,非成员函数和静态成员函数是非常有用的,将非成员函数放在名字空间内将避免污染全局作用域。

缺点:

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

结论:

  • 有时,把函数的定义同类的实例脱钩时有益的,甚至是必要的。这样的函数可以被定义成为静态成员,或者非成员函数。非成员函数不应依赖于外部变量,应尽量置于某个名字空间内。相比单纯为了封装若干不共享任何静态数据的静态成员函数而创建类,不如使用 2.1 名字空间。
  • 定义在同一编译单元的函数,被其他编译单元直接调用可能会引入不必要的耦合和链接时依赖;静态成员函数对此尤其敏感。可以考虑提取到新类中,或者将函数置于独立库的名字空间内。
  • 如果你必须定义非成员函数,又只是在.cc文件中使用它,可使用匿名namespace或者“static”链接关键字(如static int Foo() {…})限定其作用域。

局部变量

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

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

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

vector<int> v;
v.push_back(1);             // 用花括弧初始化更好
v.push_back(2);

vector<int> v = {1, 2};     // 好——v一开始就初始化

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

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

静态和全局变量

禁止使用class类型的静态或者全局变量:它们会导致难以发现的bug和不确定的构造和析构函数调用顺序。不过constexpr变量除外,毕竟它们又不涉及动态初始化或者析构。

  静态生存周期的对象,即包括了全局变量,静态变量,静态类成员变量和函数静态变量,都必须是原生数据类型(POD: Plain Old Data):即int, char和float,以及POD类型的指针、数组和结构体。
  静态变量的构造函数、析构函数和初始化的顺序在C++中是不确定的,甚至是随着构建变化而变化,导致难以发现的bug,所以除了禁用类类型的全局变量,我们也不允许函数的返回值来初始化POD变量,除非该函数不涉及(比如getenv()或者getpid())任何全局变量。(函数作用域里的静态变量除外,毕竟它的初始化顺序是有明确定义的,而且只会在指令执行到她的声明那里才会发生)
  同理,全局和静态变量在程序中断时会被析构,无论所谓中断是从main()返回还是对exit()的调用。析构顺序正好与构造函数调用的顺序相反。但既然构造顺序未定义,那么析构顺序当然也就不定了。比如在程序结束时某静态变量已经被析构了,但代码还在跑——比如其它线程——并试图访问它且失败;再比如,一个静态string变量也许会在一个引用了前者的其它变量析构之前被析构掉。
  改善以上析构问题的办法之一是用quick_exit()来代替exit()并中断程序。它们的不同之处是前者不会执行任何析构,也不会执行atexit()所绑定的任何handles。如果您想在执行quick_exit()来中断执行某handler(比如刷新log),您可以把它绑定到_at_quick_exit()。如果您想在exit()和quick_exit()都用上该handler,都绑定上去即可。
  综上所述,我们只允许POD类型的静态变量,即完全禁用vector(使用C数组替代)和string(使用const char[])。
  如果您确实需要一个class类型的静态或者全局变量,可以考虑在main()函数或者pthread_once()内初始化一个指针并且永不回收。注意只能用raw指针,别用智能指针,毕竟后者的析构函数设计到上文指出的不定顺序问题。
  

总结

  1. .cc中的匿名名字空间可避免命名冲突,限定作用域,避免直接使用using关键字污染命名空间。
  2. 嵌套类符合局部使用原则,只是不能再其他头文件中前置声明,尽量不要public。
  3. 尽量不用全局函数和全局变量,考虑作用域和命名空间限制,尽量单独形成编译单元。
  4. 多线程中的全局变量(含静态成员变量)不要使用class类型(含STL容器),避免不明确行为导致的bug。
  5. 作用域的使用,除了考虑名称污染和可读性之外,主要是为了降低耦合,提高编译/执行效率。
  6. 注意using指示(using-directive)和using声明(using-declaration)的区别。
  7. 局部变量在声明的同时进行显式初始化,比起隐式初始化再赋值的两步过程要高效,同时也贯彻了计算机体系结构重要的概念局部性(locality)。
  8. 注意别在循环犯大量构造和析构的低级错误。
Google Cpp Guide 本文章主要记录内容讲解。未完成,还在持续更新… 阅读详情

相关推荐

计算机考研408复试题汇总

TCP连接是全双工的,两端都可以先挥手 其中一端完成数据发送任务后,发送一个FIN包来终止,另一端针对这个FIN包回复确认包, 直到另一端也发送请求终止数据包FIN,另一端作出确认应答,并且还要发送一个ACK=1表示确认号有效,如果没有收到这个就可以进行重传.

ca1m4n的博客 1万+

Google C++ 风格指南 - 中文版

                    from    http://code.google.com/p/google-styleguide/  版本:3.133原作者:Benjy WeinbergerCraig SilversteinGregory EitzmannMark MentovaiTashana Landray翻译:YuleFoxyospaly项目主页:Google Style Gui...

weixin_33912445的博客 430

Python实战:5分钟搞定抖音无水印视频下载(附完整代码)

本文系统介绍了抖音无水印视频下载的多种技术方案,重点解析了抖音视频的获取逻辑与去水印原理。文章提供了从零代码的浏览器插件到可编程的Python脚本的完整实现路径,并附带了详细的代码示例,帮助用户快速构建自己的抖音视频下载工具箱。

weixin_29089057的博客 847

using使用法总结

using有两种用法,一种是using declaration(申明),另一种是using directive(指示)。using declaration一次只引入命名空间的一个成员,使得在using declaration的作用域内,对该成员的访问不需要在前面加命名空间。如:using NewDevice::Exposure; using declaration可以用在不同的地方,如全局作用域或

有闻技术博客 1575

大模型学习笔记四:LangChain开发框架解析

1、模型I/O封装LLMs:大语言模型Chat Models:一般基于LLMs,但按对话结构重新封装PromptTemple:提示词模板OutputParser:解析输出2、数据连接封装Document Loaders:各种格式文件的加载器Document transformers:对文档的常用操作,如:split,filter,translate,extract metadata,etcTextr Embedding Models:文本向量化表示,用于检索等操作。

谢白羽 4282

Matlab+Matpower实战:手把手教你生成IEEE14节点FDIA攻击数据集(附完整代码)

本文提供了一份基于Matlab与Matpower工具构建IEEE14节点FDIA攻击数据集的完整实战指南。通过动态负荷数据模拟、潮流计算、状态估计及隐蔽攻击向量注入,手把手教你生成可用于电力系统网络安全研究的仿真数据集,并附有核心代码与调试技巧。

bean的博客 398

Google 代码规范 C++ 解读一:头文件与作用域

C++ 有许多强大的特性,但强大也带来了复杂性,进一步我们的使代码更容易出错,更难阅读和维护。而且对于 C++,并没有一种强制的代码规范,我们经常能看到各种各样的代码规范,所以我在编程时总会有一种不自信感:无论写什么都感觉不正规、可能有 Bug,最终无从下笔或者不停修改,降低开发效率。 对于刚开始接触代码的同学,如果没有形成一个良好的代码规范,一旦形成手指肌肉记忆了,后面调整的成本会比较高。所以学习了解代码规范势在必行。......

weixin_45004203的博客 952

从问卷到结论:手把手教你用SPSS 28完成一份完整的社科数据分析报告

本文详细介绍了如何使用SPSS 28完成社会科学研究中的数据分析报告,从问卷数据导入、清洗到描述性和推断性统计分析,再到结果呈现与报告撰写。通过实际案例演示,帮助研究者掌握SPSS 28的核心功能,提升数据分析效率与报告质量。

weixin_28717431的博客 249

c++ 代码规范

http://tctop.wikispaces.com/Google%E4%BB%A3%E7%A0%81%E9%A3%8E%E6%A0%BC%E6%8C%87%E5%8D%97%E6%95%B4%E7%90%86 写代码时必须注重代码规范。养成良好的程序风格有助于提高代码的可维护性与可阅读性。  Google推出了自己的《Google C++ 风格指南》,在这份指南中各种C++编程中遇

Creek Shi 653

【理解机器学习算法】之Clustering算法(Agglomerative Clustering)

是一种层次聚类算法,通过逐步合并或“聚集”它们来构建嵌套聚类。这种方法采用自底向上的方式构建聚类层次:它从将每个数据点作为单个聚类开始,然后迭代合并最接近的聚类对,直到所有数据点合并为一个聚类,或直到达到指定的聚类数量。优点:- 聚合聚类在距离和连接准则的选择上具有多样性,使其适用于各种数据集。- 它产生了一个层次结构,这对于不同规模的聚类数据结构是有信息量的。-缺点:- 对于大数据集来说,它可能计算成本高,因为它需要在每次迭代中计算和更新所有聚类对之间的距离。

Hyman Qiu 2688

50、压电微泵与技术设备驱动的研究分析

本文研究了压电微泵在弹性微通道中的流体流动特性及技术设备驱动的振动行为。通过建立轴对称流固耦合模型,利用FreeFem++进行数值模拟,分析了不同数量压电致动器和频率对微泵流量的影响,发现多个致动器按特定时序压缩可产生净正向流量,并提出了稳态流量的近似解析公式。同时,针对技术设备驱动系统,探讨了周期性负载引起的强迫振动特性,明确了共振条件及影响因素,并比较了主动、被动和优化设计等振动控制策略。最后展望了实验验证、多物理场耦合与智能控制等未来研究方向,为相关设备的优化设计与高效运行提供了理论支持。

convnet3designer的博客 148

Google 开源项目风格指南阅读笔记(C++版)

虽说是编程风格指南,但是干货也不少,很多C++的实用技术在里面。头文件通常每一个.cpp文件都对应一个.h文件;#define保护所有头文件都应该使用#define防止头文件被多重包含,为保证唯一性,头文件的命名应该依据所在项目源码树的全部路径。能用前置声明的地方尽量不用#include当一个头文件被包含的同时也引入了新的依赖,一旦该头文件被修改,代码就会被重新编译,如果这个头文件又包含了其他头文

爱冒险的技术宅 2364

从零开始学 PyTorch 7天路线图(完整可运行代码版)

本文提供了5天PyTorch入门教程的完整代码,涵盖从基础到实战的核心内容。Day1测试环境并介绍张量基础;Day2讲解常用张量操作;Day3演示自动求导机制;Day4实现完整线性回归模型;Day5构建MNIST手写数字识别全连接网络。所有代码可直接运行,包含GPU检测、梯度计算、模型训练和可视化等关键环节,帮助新手快速掌握PyTorch核心概念和典型应用场景。

IT老农民的博客 314

C++ Google代码风格

C++ Google代码风格0 index(扉页)0.0 声明0.1 译者前言0.2 背景headers(头文件)1.1 Self-contained 头文件1.2. #define 保护1.3. 前置声明1.4. 内联函数1.5. #include 的路径及顺序译者(acgtyrant)笔记scoping(作用域)2. 作用域2.1. 命名空间2.2. 匿名命名空间和静态变量2.3. 非成员函数...

baidu_28926495的博客 1623

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

BAML C++ SDK 代码风格指南:Google 布局与标准库命名的工程实践

本文以 [baml_language/sdks/cpp/STYLE.md](https://link.gitcode.com/i/51b97241bd9f795a24c743a694047dac) 为骨架,系统讲解 BAML C++ SDK 的代码风格约定:布局(Layout)采用 Google 风格,命名(Naming)遵循 C++ 标准库的下划线风格,以及这套约定背后的源码级实现与例外条款。读

gitblog_00688的博客 389

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Google的C++编程规范总结

文章目录引言1 格式1.1 每行代码不多于 80 个字符1.2 使用空格(Space),而不是制表符(Tab)来缩进,每次缩进4个字符1.3 指针符号*,引用符号& 的位置,写在靠近类型的地方1.4 花括号位置1.5 if, for, while等语句就算只有一行,也强制使用花括号2 命名约定2.1 使用英文单词,不能夹着拼音2.2 总体上采用骆驼命名法2.3 名字不要加类型前缀2.4 类...

蒋成的博客 5262

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Abseil代码风格指南:Google C++代码规范的实践

在现代软件开发中,代码风格一致性是保证项目可维护性和可读性的关键因素。Google的C++代码规范被业界广泛认可,而Abseil库正是这一规范的完美实践。作为Google内部C++代码库的开源版本,Abseil不仅提供了高质量的C++组件,更展示了如何在实际项目中应用Google的代码风格规范。 本文将深入解析Abseil代码库中的风格实践,帮助开发者理解和应用这些最佳实践。 ## 命名约定:...

gitblog_00685的博客 984

Google C++编程风格指南

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

skyremember的专栏 1234

C语言Google代码风格整理

想要写出整洁的代码就不得不遵循某种特定规范,在这篇文章中整理了C语言的Google代码规范。推荐刚刚接触代码的新手或是已经入门但是苦于代码编写风格的开发者阅读。

Reed_redd的博客 1197

LevelDB设计模式:Google C++代码风格深度解析 [特殊字符]

LevelDB是Google开发的一个高性能键值存储库,采用Google C++代码风格构建。这个开源项目展示了Google内部代码标准的最佳实践,为C++开发者提供了极好的学习范例。本文将深入解析LevelDB的设计模式和代码风格特点。 ## Google C++代码风格的核心原则 LevelDB严格遵循[Google C++代码风格指南](https://google.github.io/

gitblog_00077的博客 1093

《GOOGLE C++ 编程规范》读书笔记

GOOGLE C++ 规范读书笔记 1、头文件 1、使用#define避免头文件被重复包含,定义的宏为全路径+文件名; 2、能使用前置声明的地方尽量不使用#include。即如果不需要访问类定义的情况下,使用类的前置声明即可;需要类定义时,则必须得包含头文件。 3、只有当函数只有10行甚至更少时才将其定义为内联函数;内联包含循环或switch语句的函数常常是得不尝失(除非在大多数情况下

pointersky的专栏 989

google代码风格(C++)

from    http://code.google.com/p/google-styleguide/   版本:   3.133 原作者: Benjy Weinberger Craig Silverstein Gregory Eitzmann Mark Mentovai Tashana Landray 翻译: YuleFox yospaly 项目主页:

昨天的你 4010

终极指南:掌握Google C++代码风格规范的10个核心技巧

Google C++代码风格规范是业界公认的C++编程标准,为开发者提供了一套完整的代码编写指南。作为C++程序员,遵循这套规范不仅能提升代码质量,还能让团队协作更加顺畅。本文将通过10个关键技巧,带你从规范到实践全面掌握Google C++代码风格。🚀 ## 📝 为什么需要代码风格规范? 在大型项目开发中,统一的代码风格至关重要。Google C++规范强调**可读性优先**、**一致性

gitblog_00338的博客 409

[C++] 编程实践之1: Google的C++代码风格4:来自Google的奇技

来自Google的奇技  Google用了很多自己实现的技巧/工具使C++代码更加简装,我们使用C++的方式可能和你在气他地方见到的有所不同。所有权与智能指针 动态分配出的对象最好有单一且固定的所有主(owner),且通过智能指针传递所有权(ownership)。 定义: 所有权是一种登记/管理动态内存和其它资源的技术。动态分配出的对象的所有主是一个对象或者函数,后者负责确保当前者无用时就自动销

魔豆(Magicbean)的博客 628

向google学习良好的C++代码风格-(1)概述

第2学堂-专栏 3510

Google C++编程风格指南:cpplint报错信息解决汇总

Google C++编程风格指南:cpplint报错信息解决汇总

LF__plus的博客 2601
上一篇: [C++] 编程实践之1: Google的C++代码风格1:头文件
下一篇: [C++] 编程实践之1: Google的C++代码风格3:类
魔豆Magicbean
博客等级 码龄19年 146粉丝 742原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值