Hundred battles c++ (3)

C++ memory structure

 

Heap: It is manually allocated and released by the programmer, which is completely different from the heap in the data structure, and the allocation method is similar to a linked list. It is allocated by malloc (c language) or new (c++), and released by free (c language) and delete (c++). If the programmer does not release it, it will be released by the system after the program ends. The pile grows from low to high. Big space, great flexibility, slow speed.

Stack: It is automatically allocated and released by the compiler to store the parameter values ​​​​of functions and the values ​​​​of local variables. The operation mode is similar to the stack in the data structure. Grow from high to low. Small space, poor flexibility

Global (static) storage area: store global variables and static variables. Including the data segment (global initialization area) and the BSS segment (global uninitialized area), the initialized global variables and static variables are stored in the data segment, and the uninitialized global variables and uninitialized static variables are stored in the BSS segment. Released by the system after the program ends. Among them, the characteristic of the BSS segment is that the BSS segment will be automatically cleared to 0 before the program is executed. Randomly, uninitialized global variables and static variables have become 0 before the program is executed.

Literal constant area: The constant string is placed here. Released by the system after the program ends.

Program code area: store the binary code of the function body.

The definition of a constant in C++ is a top-level const plus an object type, and the constant definition must be initialized. For local objects, constants are stored in the stack area, and for global objects, constants are stored in the global / static storage area. For literal constants, the constant is stored in the constant store.

 Talk about the difference between C++ and C

In terms of design thinking:

C++ is an object-oriented language while C is a procedural-oriented structured programming language

Syntactically:

C++ has three characteristics: encapsulation, inheritance and polymorphism

Compared with C, C++ adds many more type-safe functions, such as mandatory type conversion,

C++ supports paradigm programming, such as template classes, function templates, etc.

Please tell me about the smart pointer in c++ that you understand. Four smart pointers shared_ptr, unique_ptr, weak_ptr, auto_ptr

The role of the smart pointer is to manage a pointer, because there are the following situations: the allocated space is forgotten to be released at the end of the function, resulting in a memory leak. Using a smart pointer can avoid this problem to a large extent, because a smart pointer is a class. When it exceeds the scope of the class, the class will automatically call the destructor, and the destructor will automatically release the resource. So the working principle of the smart pointer is to automatically release the memory space at the end of the function, without manually releasing the memory space.

1. auto_ptr ( c++98 solution, cpp11 has been abandoned)

Adopt an ownership model.

auto_ptr< string> p1 (new string ("I reigned lonely as a cloud.”));

auto_ptr<string> p2;

p2 = p1; //auto_ptr will not report an error .

No error will be reported at this time, p2 deprives the ownership of p1 , but accessing p1 when the program is running will report an error. So the disadvantage of auto_ptr is: there is a potential memory corruption problem!

2 , unique_ptr (replace auto_ptr )

unique_ptr implements the concept of exclusive ownership or strict ownership, ensuring that only one smart pointer can point to the object at a time. It is especially useful to avoid resource leaks ( such as " forgot to call delete because an exception occurred after creating an object with new ") .

Adopt the ownership model, or the above example

unique_ptr<string> p3 (new string ("auto"));           //#4

unique_ptr<string> p4                           //#5

p4 = p3;// An error will be reported at this time! !

The compiler considers p4=p3 illegal, avoiding the problem that p3 no longer points to valid data. Therefore, unique_ptr is safer than auto_ptr .

In addition, unique_ptr is smarter: when a program tries to assign one unique_ptr to another, if the source unique_ptr is a temporary rvalue, the compiler allows it ; if the source unique_ptr will exist for a while, the compiler will prohibit it. for example:

unique_ptr<string> pu1(new string ("hello world"));

unique_ptr<string> pu2;

pu2 = pu1;                                          // #1 not allowed

unique_ptr<string> pu3;

pu3 = unique_ptr<string>(new string ("You"));           // #2 allowed

where #1 leaves a dangling unique_ptr(pu1) which could lead to hazards. And #2 doesn't leave a dangling unique_ptr because it calls the unique_ptr 's constructor, which creates a temporary object that will be destroyed after its ownership is relinquished to pu3 . This contingent behavior shows that unique_ptr is superior to auto_ptr which allows both assignments .

Note: If you really want to perform operations similar to #1 , you can safely reuse this pointer by assigning it a new value. C++ has a standard library function std::move() that allows you to assign one unique_ptr to another. For example:

unique_ptr<string> ps1, ps2;

ps1 = demo("hello");

ps2 = move(ps1);

ps1 = demo("alexia");

cout << *ps2 << *ps1 << endl;

3shared_ptr

shared_ptr implements the concept of shared ownership. Multiple smart pointers can point to the same object, and the object and its related resources will be released when the " last reference is destroyed " . It can be seen from the name share that resources can be shared by multiple pointers, and it uses a counting mechanism to indicate that resources are shared by several pointers. You can view the number of resource owners through the member function use_count() . In addition to being constructed by new , it can also be constructed by passing in auto_ptr, unique_ptr, and weak_ptr . When we call release() , the current pointer releases ownership of the resource and the count is decremented by one. When the count is equal to 0 , the resource will be freed.

shared_ptr is to solve the limitation of auto_ptr on object ownership (auto_ptr is exclusive ), and provides a smart pointer that can share ownership on the mechanism of using reference counting.

Member function:

use_count returns the number of reference counts

unique returns whether it is exclusive ownership (use_count is 1)

swap swaps two shared_ptr objects ( that is, swaps owned objects )

reset gives up the ownership of the internal object or changes the owned object , which will cause the reduction of the reference count of the original object

Get returns the internal object ( pointer ). Since the () method has been overloaded , it is the same as using the object directly . For example, shared_ptr<int> sp(new int(1)); sp and sp.get() are equivalent of

4weak_ptr

weak_ptr is a smart pointer that does not control the life cycle of the object . It points to an object managed by shared_ptr . The memory management of the object is the shared_ptr that is strongly referenced . weak_ptr only provides a means of access to the managed object. The purpose of weak_ptr design is to introduce a smart pointer to assist shared_ptr to cooperate with shared_ptr . It can only be constructed from a shared_ptr or another weak_ptr object . Its construction and destruction will not cause the increase or decrease of the reference count. weak_ptr is used to solve the deadlock problem when shared_ptr refers to each other , (to avoid looping) if two shared_ptr refer to each other , then the reference count of these two pointers can never drop to 0, and the resource will never be released. It is a weak reference to the object and does not increase the reference count of the object, and shared_ptrThey can be converted to each other, shared_ptr can be directly assigned to it, and it can obtain shared_ptr by calling the lock function .

Introducing smart pointers

Smart pointers are mainly used to manage memory allocated on the heap, which encapsulates ordinary pointers into a stack object. When the life cycle of the stack object ends, the allocated memory will be released in the destructor to prevent memory leaks. The most commonly used smart pointer type in C++11 is shared_ptr, which uses a reference counting method to record how many smart pointers the current memory resource is referenced by. This reference counted memory is allocated on the heap. The reference count increases by 1 when a new one is added , and the reference count decreases by one when it expires. Only when the reference count is 0 , the smart pointer will automatically release the referenced memory resource. When initializing shared_ptr, an ordinary pointer cannot be directly assigned to a smart pointer, because one is a pointer and the other is a class. Ordinary pointers can be passed in through the make_shared function or through the constructor. And ordinary pointers can be obtained through the get function.

Smart pointer memory leaks

  1. The ownership of auto_ptr is deprived by another pointer, accessing the original pointer again will cause a crash (not strictly a memory leak)
  2. shared_ptr forms a loop, forming a deadlock, and the memory can never be released

Guess you like

Origin blog.csdn.net/hebtu666/article/details/127204766