此图来自 一张图总结Google C++编程规范(Google C++ Style Guide)
具体细节,娓娓道来。
本章来自于官方文档的摘录. Google C++ Style Guide
Header files should be self-contained (compile on their own) and end in .h. Non-header files that are meant for inclusion should end in .inc and be used sparingly.
___H_
.. For example, the file foo/src/bar/baz.h
in project foo
should have the following guard:
#ifndef FOO_BAR_BAZ_H_
#define FOO_BAR_BAZ_H_
...
#endif // FOO_BAR_BAZ_H_
A “forward declaration” is a declaration of a class, function, or template without an associated definition.
#include
In dir/foo.cc or dir/foo_test.cc, whose main purpose is to implement or test the stuff in dir2/foo2.h, order your includes as follows:
For example, the includes in google-awesome-project/src/foo/internal/fooserver.cc
might look like this:
#include "foo/server/fooserver.h"
#include
#include
#include
#include "base/basictypes.h"
#include "base/commandlineflags.h"
#include "foo/server/bar.h"
#include "foo/public/fooserver.h"
#include "base/port.h" // For LANG_CXX11.
#ifdef LANG_CXX11
#include
#endif // LANG_CXX11
// In the .h file
namespace mynamespace {
// All declarations are within the namespace scope.
// Notice the lack of indentation.
class MyClass {
public:
...
void Foo();
};
} // namespace mynamespace
// In the .cc file
namespace mynamespace {
// Definition of functions is within scope of the namespace.
void MyClass::Foo() {
...
}
} // namespace mynamespace
using namespace XXX
, 如 using namespace std
using
, 如 using std::string
inline namespace
.int i;
i = f(); // Bad -- initialization separate from declaration.
int j = g(); // Good -- declaration has initialization.
std::vector<int> v;
v.push_back(1); // Prefer initializing using brace initialization.
v.push_back(2);
std::vector<int> v = {
1, 2}; // Good -- v starts initialized.
//Variables needed for if, while and for statements should normally be declared within those statements,
// so that such variables are confined to those scopes. E.g.:
while (const char* p = strchr(str, '/')) str = p + 1;
// There is one caveat: if the variable is an object, its constructor is invoked every time
// it enters scope and is created, and its destructor is invoked every time it goes out of scope.
// Inefficient implementation:
for (int i = 0; i < 1000000; ++i) {
Foo f; // My ctor and dtor get called 1000000 times each.
f.DoSomething(i);
}
// It may be more efficient to declare such a variable used in a loop outside that loop:
Foo f; // My ctor and dtor get called once each.
for (int i = 0; i < 1000000; ++i) {
f.DoSomething(i);
}
Init()
函数中, 注意 Init 不要滥用// foo.h
class Foo {
public:
// Factory method: creates and returns a Foo.
// May return null on failure.
static std::unique_ptr<Foo> Create();
// Foo is not copyable.
Foo(const Foo&) = delete;
Foo& operator=(const Foo&) = delete;
private:
// Clients can't invoke the constructor directly.
Foo();
};
// foo.c
std::unique_ptr<Foo> Foo::Create() {
// Note that since Foo's constructor is private, we have to use new.
return absl::WrapUnique(new Foo());
}
explicit
std::unique_ptr
is an example of a movable but not copyable type (since the value of the source std::unique_ptr
must be modified during assignment to the destination)class Copyable {
public:
Copyable(const Copyable& rhs) = default;
Copyable& operator=(const Copyable& rhs) = default;
// The implicit move operations are suppressed by the declarations above.
};
class MoveOnly {
public:
MoveOnly(MoveOnly&& rhs);
MoveOnly& operator=(MoveOnly&& rhs);
// The copy operations are implicitly deleted, but you can
// spell that out explicitly if you want:
MoveOnly(const MoveOnly&) = delete;
MoveOnly