C ++ programming skills note-taking (continually updated)

table of Contents

Preface: C ++ language is profound, complex characteristics takes Beijing as Ring, inherited disorder takes like incest.

But it is still my most familiar and must be used in game development language, pick out this article for some personal feel important provisions / experience / skills to record summary.
Finally, the article lists some of the books I've seen C ++ / blog, etc., for easy reference.

In fact've written the same notes Bowen, now with markdown "reset" it.

Class / object


1. Multi polymorphic base class destructor should always be public virtual, or should be protected

When the object to be released polymorphic base class pointer, the destructor for the correct order, so as to have to execute by means of virtual destructor derived class destructor then the base class.
When the base class does not matter polymorphism, the base class destructor declarations may be protected, and also used without consuming virtual.

2. The compiler will generate a default configuration implicitly, copy constructor, assignment replication, destructor, (C ++ 11) configured to move, (C ++ 11) moves inline function assignment

When you use the above function in your code and do not declare the function, it will default to generate the corresponding function.
Special, when you declare a constructor (with or without parameters), are not implicitly generated default constructor.
But implicitly generated functions than their handwriting function (even if the same behavior) higher efficiency, because after a special optimizing compilers.

(c ++ 11) when you need to generate more explicitly disable a function, you can declare the function = delete
For example:

Type(const Type& t) = delete;

(c ++ 11) when you need to explicitly generate more than a default function, the function may declare = default
example:

Type(Tpye && t) = default;

3. Do not throw an exception in the destructor, also try to avoid throwing an exception in the constructor

If the destructor throw an exception, the destructor may cause a premature end, which could lead to some resources are not properly released.
If the constructor throws an exception, you can not call the destructor, which may result in an exception occurs before successfully allocated some resources, failed to execute properly release behavior destructor.

template


1. Do not function template partial specialization, choosing instead to overloaded functions.

The compiler to select the non-matching function template function (heavy load function), and then select a template function, and finally selection bias Laid template function.
When a match to a template function, it will not select a different template matching function, even if there is another template's function is more suitable for the partial specialization function.
So it is likely to cause the compiler does not choose partial specialization template function you want.

2. (C ++ 11) Do not overload forwarding function references, or other alternatives

Forwarding function references in C ++ is the most greedy function, easy for implicit conversion required arguments do not want to match the forward reference to the function. (E.g., below)

template<class T>
  void f(T&& value);

void f(int a);

//当使用f(long类型的参数)或者f(short类型的参数),则不会匹配int版本而是匹配到转发引用的版本

alternative plan:

  1. Discard overloaded. Or transfer into another function name const T & parameter.
  2. The use of more complex label template assignment or restrictions (not recommended).

function


When 1. (C ++ 11) disable a function that uses = delete rather than private

There are four reasons:

  • private function still need to write the definition (even if it is empty implementation),
  • Derived classes covering potential possibility to disable the function name,
  • "= Delete" syntax is more intuitive than private grammar reflect the characteristics of the function is disabled,
  • In the preparation of non-class function, we can not provide private property.

= Delete the general class of functions should be public, since the compiler to detect accessibility of disabled retest

2. (C ++ 11) lambda expression is generally a function object. Particularly, in the absence of the capture function pointer.

Compiler will actually produce a function expression for each type of object when lambda expressions, and the function object constructor out.
Specially, lambda expressions when no capture, will be compiled into a function, which is an expression of the function pointer (after all function more efficiently than the function object).
So when some old C ++ API only accepts a function pointer and does not accept std :: function can be used to capture the lamdba no expression.

3. (C ++ 11) as far as possible using lamada expression instead of std :: bind

Direct way of example, assuming the following function Func:

void Func(int a, float b);

Now let us bind 2.0f on the Func as a parameter b, transforming a void (int a) of the function object.

std::function<void(int)> f;
float b = 2.0f;

//std::bind写法
f = std::bind(Func, std::placeholders::_1, b);
f(100);

//lambda表达式写法
f = [b](int a) {Func(a, b); };
f(100);

We can see the use std :: bind will be very pretty intuitive, have to pay attention placeholder position order.
The use of lambda expressions can make code becomes very simple and elegant.

4. (C ++ 11) using lambda expressions, a default capture mode to avoid

By reference to the default capture is likely to cause a reference vacant, while displaying a reference to capture more easily capture remind us which variable is referenced, making it easier to sort out the references of the life cycle.
The default value is captured by lambda misleading formula is self-consistent (i.e., not dependent on external). The following is a typical example:

void test() {
   static int a = 0;
   auto func = [=]() {
   return a + 2;
   };
   a++;
   int result = func();
}

Since the default capture, you think that is a copy by value in the past, so there will always be expected to result 2. But in fact you are calling a static variable with a scope, no copy behavior.

So, whether it is by value or reference, as much as possible the specified variable, rather than using the default capture.

Memory-related


1. Check whether the new failure is usually pointless.

new is almost always successful, most modern operating system to take the process of inerting Memory allocation (ie not allocate memory requests immediate memory, when using only slowly and distribution).
So when using a new, generally do not allocate memory immediately, so can not really detect if memory will be exhausted.

2. Try to avoid multiple new type with a lightweight, but a large area of ​​redistribution to new times.

Every new when, in fact, will allocate additional memory to store the information in a region, but many times is assigned to the lightweight type of memory, can cause a bloated memory information.
And when you remove these areas, it is easy to cause a lot of block memory fragmentation, leading to memory utilization is not high.
Should be used so that the way the memory pool, to a new large area, lightweight type from the memory to the re-allocation region.

STL standard library


1. (C ++ 11) using emplace / emplace_back / emplace_front instead of insert / push_back / push_front

The maximum effect is to emplace avoid unnecessary temporary variable, because it can be directly on the respective position of the container constructed according to a variable parameter.
And insert / push_back / push_front operation will first construct a temporary variable parameter, and temporary variables to move the respective container positions.

2. Remove iterators need to be cautious while traversing a container

Remove container sequence iterator iterator will destroy itself and the following, remove a node iterator container destroys itself, resulting in the collapse of traversal cycle (cycle through the container depends on the original iterator).

Two worth learning the right approach:

auto it = vec.begin();
while (it != vec.end()){
    if (...){
        // 顺序式容器的erase()会返回紧随被删除元素的下一个元素的有效迭代器
        it = vec.erase(it);
    }
    else{
        it++;
    }
}
auto it = list.begin();
while (it != list.end()){
    if (...) {
        t.erase(it++);
    }
    else {
        it++;
    }
}

at 3. container () border checks, [] is not a boundary check

STL small details. In addition std :: vector Of the std :: bitset [] provided that copies values, rather than by reference.

4.sort () is <comparison operator, if they are equal, it must be returned fails.

The STL sort algorithm is basically fast row, is unstable sort.
Return success if both relatively equal, the sort of instability prone infinite loop, causing the program to crash.

5. Always remember that less time complexity does not mean higher efficiency

STL containers, in particular, set, map, with a lot of O (logN) operating speed, but it does not mean that is the best choice, because it hides the complexity often represent a large constant facts.

For example, said mainstream implementation is based on a collection of red-black tree, based on the storage node, and each insert / delete nodes means that calling a system memory allocation / release memory function. This vector is compared to other vector vessel only once all operating system allocates memory (ideally speaking), actually a lot slower.

Furthermore, the vector CPU cache more friendly containers, such containers easily traverse the cache hit, the node is relatively easy to hit the container fails.

In summary, if you want to choose the most suitable container, do not place undue reliance on the complexity of the time, unless you are very thorough understanding of STL containers, or multiple efficiency test on each container.

Optimization and Efficiency


1. Use ++ i instead of i ++ as possible

This is a classic problem in C ++ commonplace, for when int / unsigned and other built-in types, ++ i and i ++ seems to be no difference in efficiency.
However, when using an iterator or other custom types, i ++ often have to create an additional copy for return to values, while ++ i return it directly itself.

2. In the late encounter performance bottlenecks, as a last resort when using inline

Modern compilers are very intelligent, very often written inline the function of the compiler will automatically inline help you, even when you should not inline explicit written inline compiler may also be considered should not be inline.
That is explicitly written inline just a suggestion to the compiler, it will not necessarily be accepted.
So do not premature optimization in the development of premature considering inline, but if you encounter performance bottlenecks consider using explicit written inline, but most of this time you should consider is that you write an algorithm efficiency.

3. Try not to use dynamic_cast and RTTI disabled

Rely dynamic_cast code can often be solved with a multi-state virtual function, virtual function polymorphism and more elegant. Therefore, as far as possible to avoid writing dynamic_cast.
Further characteristics may be will disable related RTTI dynamic_cast to disable this feature can improve the efficiency of the program (each less bloated RTTI class information).

abnormal


1. (C ++ 11) if the guarantee does not throw an exception, you should use noexpect exception specifications, do not declare an exception specifications.

No statement exception specification, meaning it is possible to throw any exceptions.
No statement abnormal function compared to specifications, noexpect function can be optimized compiler (does not have to unlock the stack when an exception occurs), and clearly express their guarantee without exception.

Miscellaneous


When 1. (C ++ 17) of any need to use a variable type, using std :: any, std :: variant instead of union

c is inherited from the union to the characteristic, it may not be members with constructor, destructor, custom c ++ to copy constructor class.
So best not to use the union, but with std :: any or std :: variant, the current C ++ 17 has been introduced <any> Library and <variant> library.

2. (C ++ 11) auto can deduce the type of typed, and can be derived decltype typed statement

int& value = 233;
auto a = value;//auto是int类型
decltype(auto) b = value; //decltype(auto)是int&类型

That auto derivation types will abandon quoted in nature and can be derived decltype full declaration type.

3. (C ++ 11) instead of using nullptr 0 or NULL

NULL is something left over from the C language, is to define the macro to zero, likely to cause ambiguity pointers and integers.
The nullptr good to avoid the nature of integers.

4. (C ++ 11) using enum class syntax provides enumerated type defined range

C brings enum enumeration type syntax is allowed implicit conversion, potentially resulting in the programmer does not want to convert happen.
The C ++ enum class 11 will prevent the implicit conversion, the programmer needs to display conversion

enum class Color{Red,Blue,Green};
Color color = Color::Red;
int i = static<int>(color);

5. (C ++ 11) as long as the potential of computable functions compile / variables, use constexpr

Some functions allow constexpr / variables can be computed at compile time, run operation can be reduced. (Regarded template unary landscaping grammar)
Furthermore, constexpr if accepted runtime variables / parameters, it will become operational in the calculation.
That is to say it can act as compile operation can also be run operation, the context of broader scope than non constexpr.

reference


  • "C ++ Primer Plus": the original entry books C ++ language.
  • "C ++ Programming Language (Special Edition)": written in C ++ father of entry materials, but in fact should be considered as the range of reference books between the starter and advanced (for query syntax).
  • "Effective C ++": C ++ Advanced books, in-depth understanding and experience
  • "More Effective C ++": C ++ Advanced books, in-depth understanding and experience
  • "Depth exploration of C ++ Object Model": C ++ Advanced books, in-depth understanding
  • "Expectional C ++": C ++ Advanced books, in-depth understanding and experience
  • "High-speed started C ++ 11/14/17" : C ++ 11/14/17 primer introduces 11/14/17 the new features of C ++ usage basis, it is currently only electronic version: HTTPS: / /github.com/changkun/modern-cpp-tutorial/blob/master/book/zh-cn/toc.md
  • "Effective Modern C ++": C ++ 11/14 Advanced book introduces 11/14 in-depth understanding and experience new features part of C ++.
  • "Game Programming Gems 2": game programming comprehensive technical book, some chapters speaking C ++ experience.
  • "Game Programming Gems 3": Ibid.

C ++ is a very, very complicated language, the more the look of this aspect of the book feel more ignorant (for example, C ++ Boost).
But in the middle of learning C ++ is also important to recognize that, C ++ is a tool, not too much drill C ++ language of the dead end.
Remember: the programmer is to become an engineer, not a linguist.

Guess you like

Origin www.cnblogs.com/KillerAery/p/11601229.html