Are there any valid use cases to use new and delete, raw pointers or c-style arrays with modern C++?

前端 未结 19 1138
梦谈多话
梦谈多话 2020-11-22 07:20

Here\'s a notable video (Stop teaching C) about that paradigm change to take in teaching the c++ language.

And an also notable blog post

19条回答
  •  温柔的废话
    2020-11-22 08:01

    I think this is typically a good use case and/or guideline to follow:

    • When the pointer is local to single function's scope.
    • The dynamic memory is handled in the function and you need the heap.
    • You are not passing the pointer around and it isn't leaving the functions scope.

    PSEUDO Code:

    #include 
    
    // Texture is a class or struct defined somewhere else.
    unsigned funcToOpenAndLoadImageData( const std::string& filenameAndPath, Texture& texture, some optional flags (how to process or handle within function ) {
        // Depending on the above library: file* or iostream...
    
        // 1. OpenFile
    
        // 2. Read In Header
    
        // 3. Process Header
    
        // 4. setup some local variables.
    
        // 5. extract basic local variables from the header
        //    A. texture width, height, bits per pixel, orientation flags, compression flags etc.
    
        // 6. Do some calculations based on the above to find out how much data there is for the actual ImageData...
    
        // 7. Raw pointer (typically of unsigned char).
    
        // 8. Create dynamic memory for that pointer or array.
    
        // 9. Read in the information from the file of that amount into the pointer - array.
    
        // 10. Verify you have all the information.
    
        // 11. Close the file handle.
    
        // 12. Process some more information on the actual pointer or array itself
        // based on its orientation, its bits per pixel, its dimensions, the color type, the compression type, and or if it exists encryption type.
    
        // 13. Store the modified data from the array into Your Structure (Texture - Class/Struct).
    
        // 14. Free up dynamic memory...
    
        // 15. typically return the texture through the parameter list as a reference
    
        // 16. typically return an unsigned int as the Texture's numerical ID.    
    }
    

    This is quite effective; efficient, doesn't need any use of smart pointers; is fast especially if inlining the function. This type of function can either be a stand alone or even a member of a class. If a pattern follows this then it is quite safe to use new & delete or new[] & delete[] if done properly.

    EDIT

    In the mentioned case(s) above sometimes you want the raw pointers and you want it on the heap. Let's say you have an application that will load say 5,000 texture files, 500 model files, 20 scene files, 500-1000 audio files. You do not want your loading time to be slow, you also want it to be "cache" friendly. Texture loading is very good example of having the pointer on the heap as opposed to the functions stack because the texture could be large in size exceeding your local memory capabilities.

    In this context you will be calling these load functions once per object, but you will be calling them several times. After you loaded & created your resources or assets and stored them internally is when and where you would want to use containers instead of arrays and smart pointers instead of raw pointers.

    You will load a single asset once, but you may have 100s or 1000s of instances of it. It is with these instances that you would prefer the use of containers and the use of smart pointers to manage their memory within your application over raw pointers and arrays. The initial loading is where you would prefer to be closer to the metal without all the extra unwanted overhead.

    If you were working on a A+ class game and you could save your audience 15 to 30s or more of loading time per loading screen then you are in the winners circle. Yes care does need to be taken and yes you can still have unhandled exceptions, but no code is 100% full proof.

    This type of design is rarely prone to memory leaks except for those exceptions which can still be handled in many of the cases. Also to safely manage raw pointers, preprocessor macros work well for easy clean up.

    Many of these library types also work and deal with raw data, raw memory allocation, etc. and many times smart pointers don't necessarily fit these types of jobs.

提交回复
热议问题