These C + + pit, once stepped on, overtime is certainly unavoidable!

Time:2020-11-20

Some of the more obscure C + + pit, special summary to share here, for your reference.

1. String splicing results in coredump

 

 

The crux of the problem lies in the fact that line 9 can be compiled and passed because x + “-” will be converted into char *, and then it can be translated into “to”_ String superposition causes bug.

 

2. Map iterator deletion

Map to delete an element is usually done through the erase() function. However, it should be noted that if we pass in an iterator as a parameter of erase to delete the element pointed to by the current iterator, the iterator will be invalid after the deletion, resulting in undefined behavior.

The correct way to use it is to receive the return value of erase() and let iterator point to the next element or end() of the deleted element.

for  ( auto  iter = m.begin(); iter != m.end(); iter++) {

  if  (…)

  iter = m.erase(iter);

  }

However, there are still errors in the above code, because if the deletion is triggered, the ITER will point to the next element in the next cycle. Therefore, the correct writing method should be as follows:

  for  ( auto  iter = m.begin(); iter != m.end();) {

  if  (…) {

  iter = m.erase(iter);

  continue ;

  }  else  {

  iter++;

  }

  }

 

3. The performance of stringstream

After clear, the string stream is empty.

Stringstream is slower than snprintf in any case.

Memset is a slow function, preferring to create new objects.

The above test results are single thread, changed to multi thread, the same holds true.

It is much more efficient than STR = STR + “a”, which creates new objects.

 

4. Smart pointer (shared)_ PTR)

4.1 try to use make_ Shared initialization

Improve performance

std::shared_ptr spw(newWidget);

Memory needs to be allocated twice. Each STD:: shared_ PTRs all point to a control block, which contains the reference count of the object being pointed to and other things. The memory of this control block is in STD:: shared_ Assigned in the constructor of PTR. Therefore, if you use new directly, you need to allocate a piece of memory to the widget and another memory to the control block

autospw = std::make_shared();

One distribution is enough. This is because STD:: make_ Shared requests a separate memory block to hold both widget objects and control blocks. This optimization reduces the static size of the program because the code contains only one memory allocation call, and this speeds up code execution because memory is allocated only once. In addition, use STD:: make_ Shared eliminates some information that control blocks need to record, which potentially reduces the total memory consumption of the program.

Abnormal security

processWidget(std::shared_ptr(new widget), / / potential resource disclosure

  computePriority());

There is a risk of memory leakage in the above code. The execution of the above code is divided into three steps:

1.  new  Widget

2. shared_ PTR structure

3. computePriority

The compiler does not need to generate code in this order, but the “new widget” must be in STD:: shared_ The PTR constructor is executed before it is called. If the compiler generates the following sequence code:

1.  new  Widget

2. Execute computepriority.

3. Execute STD:: shared_ The constructor of PTR.

If an exception occurs during the execution of step 2: computepriority, the dynamically allocated widget in the first step will be leaked, because it will never be stored in the shared managed in step 3_ In PTR

4.2 smart pointer conversion like parent class

In C + +, bare pointer is allowed, so the conversion method between bare pointer and C language pointer is the same as that of C language pointer conversion. Intelligent pointer conversion can not be forced by the above methods, but must be converted by the conversion function provided by the library. The method of C + + 11 is STD:: dynamic_ pointer_ The method in cast; boost is: Boost:: dynamic_ pointer_ cast

#include

#include

#include

#include

class  Base {

  public :

  Base(){}

  virtual  ~Base() {}

};

class  D :  public  Base {

  public :

  D(){}

  virtual  ~D() {}

};

int  main()

{

/ / mode 1: first initialize sub class smart pointer, then call dynamic_. pointer_ Cast to base class intelligent pointer object

  std::shared_ptr d1 = std::make_shared();

  std::shared_ptr b1 = std::dynamic_pointer_cast(d1);

/ / mode two: first pointer to new subclass D, then call shared_ The constructor of PTR initializes the intelligent pointer of base class

  std::shared_ptr b2 = shared_ptr( new  D());

  return  0;

}

conclusion

Both mode 1 and mode 2 can realize the intelligent pointer pointing to the subclass of the base class, but it is recommended to adopt mode 1 through STD:: make_ The method of shared is used to construct the intelligent pointer, and then it is converted;

 

5. Map security search method

In other words, the writing method of map [key] is to create elements (and not necessarily initialized). Therefore, when the business logic wants to find, it is always practical to find, otherwise dirty data will be written.

 

6. Pointer construction of string

In addition to being similar to other sequential containers, STD:: string provides three additional construction methods:

String s (CP, n): s is a copy of the first n characters in the array pointed by CP, which should contain at least n characters

String s (S2, pos2): s is the copy of string S2 starting from the subscript pos2. If pos2 > S2. Size(), the behavior of the constructor is undefined

String s (S2, pos2, len2): s is the copy of string S2 starting from the subscript pos2. If pos2 > S2. Size(), the behavior of the constructor is undefined. Regardless of the value of len2, the constructor copies at most S2. Size () – pos2 characters

Std:: string does not provide string (CP, pos2, len2) construction. If the code is used in this way, it will eventually construct an array of CP pointing to a string, and then call string (S2, pos2, pos2) this way of construction.

The reason why string (CP, pos2, len2) is not provided is that it is easy to have problems using this method. CP is a pointer. When used normally, you can obtain the array length and check the incoming parameters. If two parameters are passed in, it is easy to cross the bounds.

 

7. Variable initialization

It’s always right to initialize variables, whether or not the value will be changed later. In particular, the built-in type such as int is easy to ignore initialization in class or struct, which makes the variable become random value and produces unpredictable errors. Please initialize variable! Please initialize variable!! Please initialize variables!!!

——Programming technology learning and Exchange Club ——

No matter whether you are a career change or a beginner, you can also be advanced!

It involves: C language, C + +, windows programming, network programming, QT interface development, Linux programming, game programming, hackers and so on

Recommended Today

Construction of Vue development environment and project creation under mac

start First of all, let’s take a look at the overall development environment of Vue. Homebrew: package manager under MAC system, similar to apt get under Linux, windows control panel – install and remove program Node.jsJavaScript runtime, which is similar to simultaneous interpretation in international conferences, can’t run various programming languages directly between different systems […]