mirror of
https://github.com/cpp-best-practices/cppbestpractices.git
synced 2025-12-17 11:14:35 +03:00
Edit style section for grammar and clarity
I added a few missing punctuations and cleaned up the wording in a few places to make it a little clearer. I fixed the name of the constructor in a couple of the code examples.
This commit is contained in:
89
03-Style.md
89
03-Style.md
@@ -1,8 +1,8 @@
|
|||||||
# Style
|
# Style
|
||||||
|
|
||||||
Consistency of style is more important. Second most importance is following a style that the average C++ programmer is used to reading.
|
Consistency is the most important aspect of style. The second most important aspect is following a style that the average C++ programmer is used to reading.
|
||||||
|
|
||||||
C++ allows for arbitrary-length identifier names, so there's no reason to be terse when naming variables. Use descriptive names, and be consistent in the style.
|
C++ allows for arbitrary-length identifier names, so there's no reason to be terse when naming things. Use descriptive names, and be consistent in the style.
|
||||||
|
|
||||||
* `CamelCase`
|
* `CamelCase`
|
||||||
* `snake_case`
|
* `snake_case`
|
||||||
@@ -11,27 +11,27 @@ are common examples. *snake_case* has the advantage that it can also work with s
|
|||||||
|
|
||||||
## Common C++ Naming Conventions
|
## Common C++ Naming Conventions
|
||||||
|
|
||||||
* Types start with capitals: `MyClass`
|
* Types start with upper case: `MyClass`.
|
||||||
* functions and variables start with lower case: `myMethod`
|
* Functions and variables start with lower case: `myMethod`.
|
||||||
* constants are all capital: `const double PI=3.14159265358979323;`
|
* Constants are all upper case: `const double PI=3.14159265358979323;`.
|
||||||
|
|
||||||
C++ Standard Library (and other well-known C++ libraries like [Boost](http://www.boost.org/)) use these guidelines:
|
C++ Standard Library (and other well-known C++ libraries like [Boost](http://www.boost.org/)) use these guidelines:
|
||||||
|
|
||||||
* Macro names use uppercase with underscores: `INT_MAX`
|
* Macro names use upper case with underscores: `INT_MAX`.
|
||||||
* Template parameter names use camel case: `InputIterator`
|
* Template parameter names use camel case: `InputIterator`.
|
||||||
* All other names use snake case: `unordered_map`
|
* All other names use snake case: `unordered_map`.
|
||||||
|
|
||||||
## Distinguish Private Object Data
|
## Distinguish Private Object Data
|
||||||
|
|
||||||
Name private data with a `m_` prefix to distinguish it from public data. `m_` stands for "member" data
|
Name private data with a `m_` prefix to distinguish it from public data. `m_` stands for "member" data.
|
||||||
|
|
||||||
## Distinguish Function Parameters
|
## Distinguish Function Parameters
|
||||||
|
|
||||||
The most important thing is consistency within your codebase, this is one possibility to help with consistency.
|
The most important thing is consistency within your codebase; this is one possibility to help with consistency.
|
||||||
|
|
||||||
Name function parameters with an `t_` prefix. `t_` can be thought of as "the", but the meaning is arbitrary. The point is to distinguish function parameters from other variables in scope while giving us a consistent naming strategy.
|
Name function parameters with an `t_` prefix. `t_` can be thought of as "the", but the meaning is arbitrary. The point is to distinguish function parameters from other variables in scope while giving us a consistent naming strategy.
|
||||||
|
|
||||||
By using `t_` for parameters and `m_` for module data, we can have consistency with both public members of structs and private members of classes.
|
By using `t_` for parameters and `m_` for member data, we can have consistency with both public members of structs and private members of classes.
|
||||||
|
|
||||||
Any prefix or postfix can be chosen for your organization. This is just one example. *This suggestion is controversial, for a discussion about it see issue [#11](https://github.com/lefticus/cppbestpractices/issues/11).*
|
Any prefix or postfix can be chosen for your organization. This is just one example. *This suggestion is controversial, for a discussion about it see issue [#11](https://github.com/lefticus/cppbestpractices/issues/11).*
|
||||||
|
|
||||||
@@ -41,17 +41,17 @@ struct Size
|
|||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
|
|
||||||
ValueType(int t_width, int t_height) : width(t_width), height(t_height) {}
|
Size(int t_width, int t_height) : width(t_width), height(t_height) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// this version might make sense for thread safety or something,
|
// This version might make sense for thread safety or something,
|
||||||
// but more to the point, sometimes we need to hide data, sometimes we don't
|
// but more to the point, sometimes we need to hide data, sometimes we don't.
|
||||||
class PrivateSize
|
class PrivateSize
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int width() const { return m_width; }
|
int width() const { return m_width; }
|
||||||
int height() const { return m_height; }
|
int height() const { return m_height; }
|
||||||
ValueType(int t_width, int t_height) : m_width(t_width), m_height(t_height) {}
|
PrivateSize(int t_width, int t_height) : m_width(t_width), m_height(t_height) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_width;
|
int m_width;
|
||||||
@@ -64,7 +64,7 @@ class PrivateSize
|
|||||||
|
|
||||||
## Don't Name Anything Starting With `_`
|
## Don't Name Anything Starting With `_`
|
||||||
|
|
||||||
If you do, you risk broaching on names reserved for implementation use:
|
If you do, you risk colliding with names reserved for compiler and standard library implementation use:
|
||||||
|
|
||||||
http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier
|
http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier
|
||||||
|
|
||||||
@@ -94,12 +94,12 @@ private:
|
|||||||
|
|
||||||
## Enable Out-of-Source-Directory Builds
|
## Enable Out-of-Source-Directory Builds
|
||||||
|
|
||||||
Make sure generated files go into build folder, not the source folder
|
Make sure generated files go into an output folder that is separate from the source folder.
|
||||||
|
|
||||||
|
|
||||||
## Use `nullptr`
|
## Use `nullptr`
|
||||||
|
|
||||||
C++11 introduces `nullptr` which is a special type denoting a null pointer value. This should be used instead of `0` or `NULL` to indicate a null pointer.
|
C++11 introduces `nullptr` which is a special value denoting a null pointer. This should be used instead of `0` or `NULL` to indicate a null pointer.
|
||||||
|
|
||||||
## Comments
|
## Comments
|
||||||
|
|
||||||
@@ -123,12 +123,12 @@ int myFunc()
|
|||||||
*/
|
*/
|
||||||
```
|
```
|
||||||
|
|
||||||
which would be impossible if the function comment header used `/* */`
|
which would be impossible if the function comment header used `/* */`.
|
||||||
|
|
||||||
## Never Use `using namespace` in a Header File
|
## Never Use `using namespace` in a Header File
|
||||||
|
|
||||||
This causes the name space you are `using` to be pulled into the namespace of the header file.
|
This causes the namespace you are `using` to be pulled into the namespace of all files that include the header file.
|
||||||
It litters the namespace and it may lead to name collisions in the future.
|
It pollutes the namespace and it may lead to name collisions in the future.
|
||||||
Writing `using namespace` in an implementation file is fine though.
|
Writing `using namespace` in an implementation file is fine though.
|
||||||
|
|
||||||
|
|
||||||
@@ -157,13 +157,14 @@ Leaving them off can lead to semantic errors in the code.
|
|||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
// Bad Idea
|
// Bad Idea
|
||||||
// this compiles and does what you want, but can lead to confusing
|
// This compiles and does what you want, but can lead to confusing
|
||||||
// errors if close attention is not paid.
|
// errors if modification are made in the future and close attention
|
||||||
|
// is not paid.
|
||||||
for (int i = 0; i < 15; ++i)
|
for (int i = 0; i < 15; ++i)
|
||||||
std::cout << i << std::endl;
|
std::cout << i << std::endl;
|
||||||
|
|
||||||
// Bad Idea
|
// Bad Idea
|
||||||
// the cout is not part of the loop in this case even though it appears to be
|
// The cout is not part of the loop in this case even though it appears to be.
|
||||||
int sum = 0;
|
int sum = 0;
|
||||||
for (int i = 0; i < 15; ++i)
|
for (int i = 0; i < 15; ++i)
|
||||||
++sum;
|
++sum;
|
||||||
@@ -171,7 +172,7 @@ for (int i = 0; i < 15; ++i)
|
|||||||
|
|
||||||
|
|
||||||
// Good Idea
|
// Good Idea
|
||||||
// It's clear which statements are part of the loop (or if block, or whatever)
|
// It's clear which statements are part of the loop (or if block, or whatever).
|
||||||
int sum = 0;
|
int sum = 0;
|
||||||
for (int i = 0; i < 15; ++i) {
|
for (int i = 0; i < 15; ++i) {
|
||||||
++sum;
|
++sum;
|
||||||
@@ -205,26 +206,26 @@ It also makes it possible to have two separate files next to each other on one s
|
|||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
// Bad Idea. Requires extra -I directives to the compiler
|
// Bad Idea. Requires extra -I directives to the compiler
|
||||||
// and goes against standards
|
// and goes against standards.
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <includes/MyHeader.hpp>
|
#include <includes/MyHeader.hpp>
|
||||||
|
|
||||||
// Worse Idea
|
// Worse Idea
|
||||||
// requires potentially even more specific -I directives and
|
// Requires potentially even more specific -I directives and
|
||||||
// makes code more difficult to package and distribute
|
// makes code more difficult to package and distribute.
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <MyHeader.hpp>
|
#include <MyHeader.hpp>
|
||||||
|
|
||||||
|
|
||||||
// Good Idea
|
// Good Idea
|
||||||
// requires no extra params and notifies the user that the file
|
// Requires no extra params and notifies the user that the file
|
||||||
// is a local file
|
// is a local file.
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "MyHeader.hpp"
|
#include "MyHeader.hpp"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Initialize Member Variables
|
## Initialize Member Variables
|
||||||
...with the member initializer list
|
...with the member initializer list.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
// Bad Idea
|
// Bad Idea
|
||||||
@@ -244,7 +245,7 @@ private:
|
|||||||
// Good Idea
|
// Good Idea
|
||||||
// C++'s member initializer list is unique to the language and leads to
|
// C++'s member initializer list is unique to the language and leads to
|
||||||
// cleaner code and potential performance gains that other languages cannot
|
// cleaner code and potential performance gains that other languages cannot
|
||||||
// match
|
// match.
|
||||||
class MyClass
|
class MyClass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -267,7 +268,7 @@ private:
|
|||||||
```
|
```
|
||||||
inside the class body. This makes sure that no constructor ever "forgets" to initialize a member object.
|
inside the class body. This makes sure that no constructor ever "forgets" to initialize a member object.
|
||||||
|
|
||||||
Use brace initialization, it does not allow narrowing at compile-time:
|
Use brace initialization; it does not allow narrowing at compile-time:
|
||||||
```cpp
|
```cpp
|
||||||
// Best Idea
|
// Best Idea
|
||||||
|
|
||||||
@@ -283,16 +284,16 @@ Forgetting to initialize a member is a source of undefined behavior bugs which a
|
|||||||
|
|
||||||
## Always Use Namespaces
|
## Always Use Namespaces
|
||||||
|
|
||||||
There is almost never a reason to declare an identifier in the global namespaces. Instead, functions and classes should exist in an appropriately named namespace or in a class inside of a namespace. Identifiers which are placed in the global namespace risk conflicting with identifiers from other libraries (mostly C, which doesn't have namespaces).
|
There is almost never a reason to declare an identifier in the global namespace. Instead, functions and classes should exist in an appropriately named namespace or in a class inside of a namespace. Identifiers which are placed in the global namespace risk conflicting with identifiers from other libraries (mostly C, which doesn't have namespaces).
|
||||||
|
|
||||||
|
|
||||||
## Use the Correct Integer Type For stdlib Features
|
## Use the Correct Integer Type for Standard Library Features
|
||||||
|
|
||||||
The standard library generally returns `size_t` for anything related to size. What exactly `size_t` is, is implementation defined.
|
The standard library generally uses `std::size_t` for anything related to size. The size of `size_t` is implementation defined.
|
||||||
|
|
||||||
In general, using `auto` will avoid most of these issues, but not all.
|
In general, using `auto` will avoid most of these issues, but not all.
|
||||||
|
|
||||||
Make sure you stick with the correct integer types and remain consistent with the C++ stdlib. It might not warn on the platform you are currently using, but it probably will when you change platforms.
|
Make sure you stick with the correct integer types and remain consistent with the C++ standard library. It might not warn on the platform you are currently using, but it probably will when you change platforms.
|
||||||
|
|
||||||
## Use .hpp and .cpp for Your File Extensions
|
## Use .hpp and .cpp for Your File Extensions
|
||||||
|
|
||||||
@@ -302,7 +303,7 @@ One particularly large project ([OpenStudio](https://github.com/NREL/OpenStudio)
|
|||||||
|
|
||||||
## Never Mix Tabs and Spaces
|
## Never Mix Tabs and Spaces
|
||||||
|
|
||||||
Some editors like to indent with a mixture of tabs and spaces by default. This makes the code unreadable to anyone not using the exact same tab indentation settings.
|
Some editors like to indent with a mixture of tabs and spaces by default. This makes the code unreadable to anyone not using the exact same tab indentation settings. Configure your editor so this does not happen.
|
||||||
|
|
||||||
## Never Put Code with Side Effects Inside an assert()
|
## Never Put Code with Side Effects Inside an assert()
|
||||||
|
|
||||||
@@ -322,17 +323,17 @@ They should be preferred to macros, because macros do not honor namespaces, etc.
|
|||||||
|
|
||||||
Operator overloading was invented to enable expressive syntax. Expressive in the sense that adding two big integers looks like `a + b` and not `a.add(b)`. Another common example is std::string, where it is very common to concatenate two strings with `string1 + string2`.
|
Operator overloading was invented to enable expressive syntax. Expressive in the sense that adding two big integers looks like `a + b` and not `a.add(b)`. Another common example is std::string, where it is very common to concatenate two strings with `string1 + string2`.
|
||||||
|
|
||||||
However, you can easily create unreadable expressions using too much or wrong operator overloading. When overloading operators, there are three basic rules to follow as described [on stackoverflow](http://stackoverflow.com/questions/4421706/operator-overloading/4421708#4421708)
|
However, you can easily create unreadable expressions using too much or wrong operator overloading. When overloading operators, there are three basic rules to follow as described [on stackoverflow](http://stackoverflow.com/questions/4421706/operator-overloading/4421708#4421708).
|
||||||
|
|
||||||
More detailed, you should keep these things in mind:
|
Specifically, you should keep these things in mind:
|
||||||
|
|
||||||
* Overloading `operator=` when handling with resources is a must, see [Consider the Rule of Zero](03-Style.md#consider-the-rule-of-zero) below.
|
* Overloading `operator=()` when handling resources is a must. See [Consider the Rule of Zero](03-Style.md#consider-the-rule-of-zero) below.
|
||||||
* For all other operators, only overload them when they are used in a context that is commonly connected to these operators. Typical scenarios are concatenating things with +, negating expressions that can be considered "true" or "false", etc.
|
* For all other operators, only overload them when they are used in a context that is commonly connected to these operators. Typical scenarios are concatenating things with +, negating expressions that can be considered "true" or "false", etc.
|
||||||
* Always be aware of the [operator precedence](http://en.cppreference.com/w/cpp/language/operator_precedence) and try to circumvent unintuitive constructs.
|
* Always be aware of the [operator precedence](http://en.cppreference.com/w/cpp/language/operator_precedence) and try to circumvent unintuitive constructs.
|
||||||
* Do not overload exotic operators such as ~ or % unless implementing a numeric type or following a well recognized syntax in specific domain.
|
* Do not overload exotic operators such as ~ or % unless implementing a numeric type or following a well recognized syntax in specific domain.
|
||||||
* [Never](http://stackoverflow.com/questions/5602112/when-to-overload-the-comma-operator?answertab=votes#tab-top) overload `operator ,` (the comma operator).
|
* [Never](http://stackoverflow.com/questions/5602112/when-to-overload-the-comma-operator?answertab=votes#tab-top) overload `operator,()` (the comma operator).
|
||||||
* Use `operator >>` and `operator <<` when dealing with streams. For example, you can overload `operator <<(std::ostream &, MyClass const &)` to enable "writing" you class into a stream, such as std::cout or an std::fstream or std::stringstream. The latter is often used to create a textual representation of a value.
|
* Use non-member functions `operator>>()` and `operator<<()` when dealing with streams. For example, you can overload `operator<<(std::ostream &, MyClass const &)` to enable "writing" your class into a stream, such as `std::cout` or an `std::fstream` or `std::stringstream`. The latter is often used to create a string representation of a value.
|
||||||
* There are more common operators to overload [described here](http://stackoverflow.com/questions/4421706/operator-overloading?answertab=votes#tab-top)
|
* There are more common operators to overload [described here](http://stackoverflow.com/questions/4421706/operator-overloading?answertab=votes#tab-top).
|
||||||
|
|
||||||
More tips regarding the implementation details of your custom operators can be found [here](http://courses.cms.caltech.edu/cs11/material/cpp/donnie/cpp-ops.html).
|
More tips regarding the implementation details of your custom operators can be found [here](http://courses.cms.caltech.edu/cs11/material/cpp/donnie/cpp-ops.html).
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user