系列综述:
目的:本系列是个人整理为了秋招面试
的,整理期间苛求每个知识点,平衡理解简易度与深入程度。
来源:材料主要源于Google开源项目风格指南进行的,每个知识点的修正和深入主要参考各平台大佬的文章,其中也可能含有少量的个人实验自证。
结语:如果有帮到你的地方,就点个赞和关注一下呗,谢谢!!!
【C++】秋招&实习面经汇总篇
点此到文末惊喜↩︎
统一的编程风格
的作用
风格
的解释
.inc
文件扩展名。<项目名>_<路径>_<文件名>_H_
// 为保证唯一性, 头文件的命名应为所在项目目录的全路径
// 例如, 项目 foo 中的头文件 foo/src/bar/baz.h 可按如下方式保护:
#ifndef FOO_BAR_BAZ_H_
#define FOO_BAR_BAZ_H_
...
#endif // FOO_BAR_BAZ_H_
类型间
的头文件要插入空行
,类型内
的可以使用字母排序
// 本文件路径为google-awesome-project/src/foo/internal/Function.cpp
//
// 1.本文件所要实现的头文件
#include "foo/public/Function.h" // 优先位置
// 2.C 系统文件
#include
#include
// 3.C++ 系统文件
#include
#include
// 4.其他库的 .h 文件
// 5.本项目内的 .h 文件
#include "base/basictypes.h"
#include "base/commandlineflags.h"
#include "foo/public/comment.inc"// 纯文本文件
// .h 文件
namespace mynamespace {
// 所有声明都置于命名空间中
// 注意不要使用缩进
class MyClass {
public:
...
void Foo();
};
} // namespace mynamespace
// .cpp文件
namespace mynamespace {
// 函数定义都置于命名空间中
void MyClass::Foo() {
...
}
// 鼓励在.cpp文件中使用匿名空间
namespace {
...
} // namespace
} // namespace mynamespace
// 正确的
namespace myproject {
namespace foo_bar {
void Function1();
void Function2();
} // namespace foo_bar
} // namespace myproject
// 错误的
namespace myproject {
class FooBar {
public:
static void Function1();
static void Function2();
};
} // namespace myproject
// 好——初始化时声明
int j = g();
// 坏——初始化和声明分离
int i;
i = f();
// 好——声明时初始化
vector<int> v = {1, 2};
// 坏
vector<int> v;
v.push_back(1);
v.push_back(2);
// 低效的实现
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);
}
int price_count_reader; // 无缩写
int num_errors; // "num" 是一个常见的写法
int num_dns_connections; // 人人都知道 "DNS" 是什么
int n; // 毫无意义.
int nerr; // 含糊不清的缩写.
int n_comp_conns; // 含糊不清的缩写.
int wgc_connections; // 只有贵团队知道是什么意思.
int pc_reader; // "pc" 有太多可能的解释了.
int cstmr_id; // 删减了若干字母.
_
进行分割// 示例
my_useful_class.cc
http_server_logs.h// 比logs.h好
.h
文件中。如果内联函数比较短,就直接将实现也放在 .h
中。// 类和结构体
class UrlTable { ...
class UrlTableTester { ...
struct UrlTableProperties { ...
// 类型定义
typedef hash_map<UrlTableProperties *, string> PropertiesMap;
// using 别名
using PropertiesMap = hash_map<UrlTableProperties *, string>;
// 枚举
enum UrlTableErrors { ...
// 函数
int count()// 只有一个单词时,不大写
void AddTableEntry()
void DeleteUrl()
void OpenFileOrDie()
void StartRpc()// 不是使用StartRPC()
// 普通变量命名
string table_name; // 好 - 用下划线.
string tablename; // 好 - 全小写.
string tableName; // 差 - 混合大小写
// 类数据成员
class TableInfo {
...
private:
string table_name_; // 好 - 后加下划线.
string tablename_; // 好.
static Pool<TableInfo>* pool_; // 好.
};
// 结构体内部的变量
struct UrlTableProperties {
string name;
int num_entries;
static Pool<UrlTableProperties>* pool;
};
// 命名空间
namespace web_search{
}
web_search::index_util
// const声明的常量
const int kDaysInAWeek = 7;// 数学中的常量表示为k
// 枚举命名,宏命名方式可能产生冲突
enum UrlTableErrors {
kOK = 0,
kErrorOutOfMemory,
kErrorMalformedInput,
};
AddTableEntry()
DeleteUrl()
OpenFileOrDie()
StartRpc()// 不是使用StartRPC()
#define ROUND(x) ...
#define PI_ROUNDED 3.14
class Test{
public:
int FunTest();
private:
int word_;// 下划线在开始位置是系统内部的变量
};
/*
** This file is part of LibreBoot progect.(项目归属)
** file_name.py - The core part of LibreBoot Progect (文件名和作用概述)
** Copyright (c) 2023-06-01 WangSen [email protected](项目完成时间和个人信息)
** Copyright (c) 2024 WangSen [email protected](在2024年你改了一点)
** All rights reserved.
**
*/
// Function:Iterates over the contents of a GargantuanTable.
// Example:
// GargantuanTableIterator* iter = table->NewIterator();
// for (iter->Seek("foo"); !iter->done(); iter->Next()) {
// process(iter->key(), iter->value());
// }
// delete iter;
class GargantuanTableIterator {
...
};
声明处
的注释描述函数功能
输入
和输出
.隐患
定义处
的注释描述函数实现
// Returns an iterator for this table. It is the client's
// responsibility to delete the iterator when it is done with it,
// and it must not use the iterator once the GargantuanTable object
// on which the iterator was created has been deleted.
//
// The iterator is initially positioned at the beginning of the table.
//
// This method is equivalent to:
// Iterator* iter = table->NewIterator();
// iter->Seek("");
// return iter;
// If you are going to immediately seek to another place in the
// returned iterator, it will be faster to use NewIterator()
// and avoid the extra seek.
Iterator* GetIterator() const;
变量名本身
足以很好说明变量用途类数据成员
和全局变量
通常要进行注释private:
// Used to bounds-check table accesses. -1 means
// that we don't yet know how many entries the table has.
int num_total_entries_;
DoSomething(); // Comment here so the comments line up.
DoSomethingElseThatIsLonger(); // Two spaces between the code and the comment.
{ // One space before comment when opening a new scope is allowed,
// thus the comment lines up with the following comments and code.
DoSomethingElse(); // Two spaces before line comments normally.
}
std::vector<string> list{
// Comments in braced lists describe the next element...
"First item",
// .. and should be aligned appropriately.
"Second item"};
DoSomething(); /* For trailing block comments, one space is fine. */
TODO 注释
表示将来某一天做某事// TODO([email protected]): Use a "*" here for concatenation operator.
// TODO(Zeke) change this to use relations.
// TODO(bug 12345): remove the "Last visitors" feature
// DEPRECATED
的注释, 以标记某接口为弃用状态. 注释可以放在接口声明前, 或者同一行., + 空格
进行区分) {
直接加空格ReturnType LongClassName::ReallyReallyReallyLongFunctionName(// 没有空格
Type par_name1, // 4个空格
Type par_name2,
Type par_name3) {// 注意空格
DoSomething(); // 函数体两个空格
...
}
int x = 0;
auto add_to_x = [&x](int n) { x += n; };
if (condition) { // 圆括号里没有空格.
... // 2 空格缩进.
} else if (...) { // else 与 if 的右括号同一行.
...
} else {
...
}
// 只要其中一个分支用了大括号, 两个分支都要用上大括号.
if (condition) {
foo;
} else {
bar;
}
// 简短语句
if (x == kFoo) return new Foo();
switch (var) {
case 0: { // 2 空格缩进
... // 4 空格缩进
break;
}
case 1: {
...
break;
}
default: {
assert(false);
}
}
while (condition) {// 圆括号前后都有空格
doing();
}
for (int i = 0; i < kSomeNumber; ++i) {// 圆括号前后都有空格
doing();
}
x = *p;
p = &x;
x = r.y;
x = r->y;
// 空格前置
char *c, *a;
const string &str;
int x = 3;
int x(3);
int x{3};
string name("Some Name");
string name = "Some Name";
string name{"Some Name"};
// 好 - 指令从行首开始
if (lopsided_score) {
#if DISASTER_PENDING // 正确 - 从行首开始
DropEverything();
# if NOTIFY // 非必要 - # 后跟空格
NotifyClient();
# endif
#endif
BackToNormal();
}
// .h头文件
class MyClass : public OtherClass {// 注意空格
public: // 注意有一个空格的缩进
// 公有的构造函数和析构函数
MyClass(); // 标准的两空格缩进
explicit MyClass(int var);// 单参构造函数的explicit声明
~MyClass() {}
// 其他函数
void SomeFunction();
void SomeFunctionThatDoesNothing() {
doing();
}
void set_some_var(int var) { some_var_ = var; }
int some_var() const { return some_var_; }
protected:
// public 放在最前面, 然后是 protected, 最后是 private
private:
// 函数部分
bool SomeInternalFunction();
// 数据部分:尾下划线法
int some_var_;
int some_other_var_;
};
// .cpp实现文件
// 如果不能放在同一行,
// 必须置于冒号后, 并缩进 4 个空格
MyClass::MyClass(int var)
: some_var_(var), some_other_var_(var + 1) {
DoSomething();
}
// 如果初始化列表需要置于多行, 将每一个成员放在单独的一行
// 并逐行对齐
MyClass::MyClass(int var)
: some_var_(var), // 4 space indent
some_other_var_(var + 1) { // lined up
DoSomething();
}
// 右大括号 } 可以和左大括号 { 放在同一行
// 如果这样做合适的话
MyClass::MyClass(int var)
: some_var_(var) {}
// 单命名空间
namespace {
void foo() { // 正确. 命名空间内没有额外的缩进.
...
}
} // namespace
// 嵌套命名空间
namespace foo {
namespace bar {
点此跳转到首行↩︎