Why should C++ programmers minimize the use of new?

Why should C++ programmers minimize the use of new?

There are two widely used memory allocation techniques: automatic allocation and dynamic allocation. Usually, they correspond to memory areas: stack and heap.
Stack
A stack always allocates memory in a sequential fashion. It can do this because it requires you to free memory in reverse order (first in first out, FILO). Many programming languages ​​employ such storage allocation techniques for local variables. It's very, very fast because it requires very little bookkeeping, and the next address assigned is implicit.
In C++, this is called automatic storage, because the storage is declared automatically. Once the current code block (delimited by {}) is executed, the memory of all variables in this block will be automatically reclaimed. This is also the moment when destructors are called to clean up resources.
Heap The
heap allows for more flexible memory allocation patterns. Bookkeeping is more complicated and allocation is slower. Because there is no implicit release point, the memory must be freed manually, using delete or delete[]. However, the lack of implicit release points is the key to the flexibility of the heap.
Reasons to use dynamic allocation
Even though using the heap is slower and can lead to memory leaks or memory fragmentation, dynamic allocation has very good use cases because it is less restrictive.
There are two main reasons to use dynamic allocation:
You don't know how much memory you need at compile time. For example, when reading a text file into a string, we usually don't know the size of the file, so we can't tell how much memory to allocate until we run the program.
· You want to allocate memory, even after leaving the current code block, the memory will not be released. For example, you might want to write a function string readfile(string path) that returns the contents of a file. In this case, even though the stack can store the entire file content, you can't use it as the return value of the function, because the memory will be freed after leaving this code segment.
Why dynamic allocation is usually unnecessary
In C++ there is a neat function called a destructor. This mechanism allows you to manage resources by aligning their lifetime with the variable's lifetime. This technique is called RAII and is special to C++. It encapsulates resources into objects. std::string is a perfect example. This snippet:

int main ( int argc, char* argv[] )
{
    
    
    std::string program(argv[0]);
}

Mutable memory is actually allocated. A std::string object allocates memory using the heap and frees it in its destructor. In this case, you don't need to manage any resources manually and still get the benefits of dynamic memory allocation.
And this snippet:

int main ( int argc, char* argv[] )
{
    
    
    std::string * program = new std::string(argv[0]);  // Bad!
    delete program;
}

It is unnecessary dynamic memory allocation. The program increases the amount of code and increases the risk of forgetting to free allocated memory, for no apparent benefit.
Why you should use automatic storage as much as possible
To sum up, using automatic storage as much as possible makes your program:
• Faster in types;
• Faster in runtime;
• Less prone to memory/resource leaks.
Additional additions
Among the mentioned issues, there are others, specifically the following class

class Line {
    
    
public:
    Line();
    ~Line();
    std::string* mString;
};

Line::Line() {
    
    
    mString = new std::string("foo_bar");
}

Line::~Line() {
    
    
    delete mString;
}

It's actually more dangerous to use than:

class Line {
    
    
public:
    Line();
    std::string mString;
};

Line::Line() {
    
    
    mString = "foo_bar";
    // note: there is a cleaner way to write this.
}

The reason is that std::string defines a copy function. Consider the following program:

int main ()
{
    
    
    Line l1;
    Line l2 = l1;
}

With the original version, this program would probably crash because it uses the same string, but deletes it twice. With the modified version, each Line instance will have its own String instance, each with its own memory, and both will be freed at the end of the program.
Other notes
For all the reasons above, extensive use of RAII is a best practice in C++. In addition, there is another benefit that is not obvious.
If you use the Line class as a building block:

class Table
 {
    
    
      Line borders[4];
 };

Then

int main ()
 {
    
    
     Table table;
 }

The allocated four std::string instances, four Line instances, one Table instance and the contents of all strings, everything is automatically freed.

おすすめ

転載: blog.csdn.net/hy2014x/article/details/113335480