The suggestion about C++ is just to standardize the code (1)

Refer to Andrey Karpov's <<42 Suggestions for C++ Programming>>

1. Don't copy and paste too many identical sentences, learn to use loops to solve problems.

example:

int tem(string a, char b) {
    
    
    if (a[0] != b) return a[0] - b;
    if (a[1] != b) return a[1] - b;
    if (a[2] != b) return a[0] - b;
    if (a[3] != b) return a[3] - b;
    if (a[4] != b) return a[4] - b;
    if (a[5] != b) return a[5] - b;
    if (a[6] != b) return a[6] - b;
}

Obviously because of copy and paste, an error occurred:

if (a[2] != b) return a[0] - b;

Here does not change a[0] to a[2].

If we write in a loop:

int tem(string a, char b) {
    
    
    for (int i = 0; i < 6; i++) {
    
    
        if (a[i] != b) return a[i] - b;
   }
}

The code is accurate and easy to write.

2. Greater than 0 does not mean 1.

example:

Function: int memcmp(const void *str1, const void *str2, size_t n)
Parameters:
str1-pointer to the memory block.
str2-Pointer to the memory block.
n-the number of bytes to be compared.
Header function: #include<memory.h>
Return value:
If the return value is <0, it means that str1 is less than str2.
If the return value> 0, it means that str2 is less than str1.
If the return value = 0, it means that str1 is equal to str2.
Function: Compare the first n bytes of storage area str1 and storage area str2.

There are many functions that return -1 when the return value is <0, but not all functions are like this, such as the memcmp we introduced above.
example:

void testMemory() {
    
    
    char str1[10];
    char str2[10];
    int ret;
    memcpy(str1, "abcdef", 6);
    memcpy(str2, "ABCDEF", 6);
    ret = memcmp(str1, str2, 5);
    if (ret == 1) {
    
    
        printf("str1大");
    }
    if (ret == -1) {
    
    
        printf("str2大");
    }
    if (ret == 0) {
    
    
        printf("一样大");
    }
}

First explain, this program can run normally on VS2019 and some compilers, but this is not the original meaning of this function at all. We need to change ret== 1 to ret>0, and change ret== -1 to ret<0.

void testMemory() {
    
    
    char str1[10];
    char str2[10];
    int ret;
    memcpy(str1, "abcdef", 6);
    memcpy(str2, "ABCDEF", 6);
    ret = memcmp(str1, str2, 5);
    if (ret > 0) {
    
    
        printf("str1大");
    }
    if (ret < 0) {
    
    
        printf("str2大");
    }
    if (ret == 0) {
    
    
        printf("一样大");
    }
}

3. Pay attention to the priority of the characters. If it is not clear, try to enclose it in parentheses.

Insert picture description here
The picture is taken directly from Baidu Baike. Source link graph of
examples:

If you want to judge whether b is equal to 1, if b is equal to 1, then add 1 to a.

void testPriority() {
    
    
    int a = 5;
    bool b = 0;
    cout << (a + (b) ? 1 : 0);
}

This is obviously wrong. The ternary operator "?:" has a very low precedence, which is lower than the precedence of these operators "/, +, <".
You can use parentheses like this:

void testPriority() {
    
    
    int a = 5;
    bool b = 0;
    cout << (a + (b ? 1 : 0));
}

4. Don't open up a temporary buffer in the loop.

example:

The alloca() function uses the stack to allocate memory. The memory allocated by alloca() will not be reclaimed until the function is executed. The stack memory allocated to the program is usually not much. When you create a new project in Visual C++, you can see that 1MB of stack memory is allocated by default. This is why if the alloca() function is in a loop, it is very Almost all available stack memory is exhausted.

Solution to the problem:

  1. Apply for memory in advance, and then use a buffer for all operations. If you need the buffer size every time. Different, apply for the largest block of memory. If it doesn't work (you don't know how much memory it will require), use method 2.
  2. Put the loop alone in a function. In this way, the buffer will be applied for and released during each iteration. If this does not work, only method 3 is left.
  3. Use malloc() or other operations instead of alloca(), or use functions like std::vector. But allocating memory in this way will take more time. If you use malloc/new, you have to consider its release. On the other hand, this way you won't have a stack overflow when you use a relatively large number to demonstrate the program to the client.

5. Try to keep the destructor simple.

The destructor can be called in the process of cleaning up the stack memory after the exception occurs, or it can be called at the end of the object's life cycle. If the destructor is called when an exception has occurred, and an exception occurs when the stack memory is cleaned, and there is an exception above the exception, the C++ library can only call terminate() to terminate the program. So we can know from it, don't throw an exception in the destructor. Exceptions in the destructor must be handled in the same destructor.
So, our destructor should be as simple as possible.

6. Use characters to represent symbols.

The following symbols can be used:

  • 0-integer 0;
  • nullptr-the null pointer in C++;
  • NULL-a null pointer in C;
  • '\0', L'\0', _T('\0')——null end;
  • 0.0, 0.0f——0 of floating point type;
  • false,FALSE——’false‘值;

7. Don't compress all operations to the same line.

Of course, I have personally met a genius player == because I am a salted fish, so I don’t like a gang liu.
example:

int testOneLine(int a,int b,int c,int d) {
    
    
    return ((b = b - a / c) + c + d - (a = a * b + c));
}

This will not help the compiler, but it does play a role in making the code more difficult to understand and making it more difficult for other programmers (or even the author himself) to understand. And the probability of this code error is relatively high.
So it can be written like this:

int testOneLine(int a,int b,int c,int d) {
    
    
    b = b - a / c;
    a = a * b + c;
    return (b + c + d - a);
}

That's much better.

8. Design the format of the table style.

Example: (This is the code of "42 Suggestions for C++ Programming" I picked up.

void adns__querysend_tcp(adns_query qu, struct timeval now) {
    
    
 ...
 if (!(errno == EAGAIN || EWOULDBLOCK || 
 errno == EINTR || errno == ENOSPC ||
 errno == ENOBUFS || errno == ENOMEM)) {
    
    
 ...
}

Obviously, the code is messy and it doesn't look easy and the code is missing an errno.
So you can change it:

if (!(errno == EAGAIN || errno == EWOULDBLOCK || 
 errno == EINTR || errno == ENOSPC ||
 errno == ENOBUFS || errno == ENOMEM))

But it still looks uncomfortable.
Change it a bit and put the symbol in front.

if (!( errno == EAGAIN
 || EWOULDBLOCK
 || errno == EINTR
 || errno == ENOSPC
 || errno == ENOBUFS
 || errno == ENOMEM))

9. Start using enum class in your code.

In standard C++, enumerated types are not type-safe. Enumeration types are treated as integers, which allows comparisons between two different enumeration types.

example:

enum class Enumeration1
{
    
    
    Val1, // 0
    Val2, // 1
    Val3 = 100,
    Val4 /* = 101 */
};
//指定类型:
int main(int argc, char** argv)
{
    
    
    Enumeration1 my=Enumeration1::Val3;
    cout<<static_cast<int>(my)<<endl;

    cout<<static_cast<double>(Enumeration2::val2)<<endl;
    return 0;
}

10. How to call another from one constructor correctly.

class A {
    
    
    int b;
    A(int a) {
    
    
        A();
    }
};

As for the constructor function, many people will reap the consequences when they want to make the code shorter and more organized. You know, constructors are not the same as ordinary functions. If we write "A::A(int x) {A(); }", a temporary unnamed class A object will be created instead of calling a parameterless constructor. This is what happens in the code above: a temporary unnamed Guess() object is created and then destroyed immediately because there is no initialized function member.

There are three ways to avoid repetitive code in the constructor.
1. The first method is to design an independent initialization function, and then call it in the two constructors.
2. The second method:

A::A(int b)
{
    
    
 new (this) A();
 ....
}

3. The third method

A::A(int b)
{
    
    
 this->A();
 ....
}

The second and third methods are more dangerous because the base class is initialized twice. Such code can cause some unobvious
bugs, which are harmful and unhelpful.
Suggest:

C++11 allows to call another constructor of the same kind in the constructor (that is, the delegation "delegation").
In this way, a constructor can use the behavior of another constructor with just a few lines of code.
Insert picture description here

A member variable of a class contains a pointer to another class. Its advantage is that it can share a resource with others. And the call and implementation are not together. It is called a compiled firewall.
Commission code:

A::A(int b) :A()
{
    
    
 ....
}

Actual column:

#include <iostream>
using namespace std;

class stringRep
{
    
    
    friend class sstring;
public:
    stringRep():count_n(0){
    
    cout<<"construct a objectStringRep"<<endl;}
    ~stringRep(){
    
    cout<<"destruct a objectStringRep"<<endl;}
    stringRep(char* chr):count_n(0){
    
    this->chr=chr;cout<<"construct a objectStringRep"<<endl;}
    char* getchr() const {
    
    return chr;}
    int get_n() const {
    
    return count_n;}
private:
    int count_n;
    char* chr;
};


class sstring
{
    
    
public:
    sstring(){
    
    cout<<"construct a objectSTRING"<<endl;}
    sstring(stringRep& sr):rep(&sr){
    
    sr.count_n++;cout<<"construct a objectSTRING"<<endl;}
    ~sstring(){
    
    (rep->count_n)--;cout<<"construct a objectString"<<endl;}
private:
    stringRep* rep;
};

transfer:

#include <iostream>
#include "delegation.h"
using namespace std;

int main()
{
    
    
    stringRep sr("乌兹 never give up!!!");
    sstring str1(sr);
    sstring str2(sr);
    sstring str3(sr);
    cout<<endl<<"count_n="<<sr.get_n()<<endl<<endl;
    cout<<sr.getchr()<<endl<<endl;
    return 0;
}

The blog of Yuyuyu referred to by the above commission. Portal

Guess you like

Origin blog.csdn.net/weixin_45743162/article/details/109544684