Scope of Dynamically Allocated Arrays in class member functions

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • emaghero
    New Member
    • Oct 2006
    • 85

    #1

    Scope of Dynamically Allocated Arrays in class member functions

    I have the following class declaration
    Code:
    class class_name{
    public:
       class_name(); // Constructor
    
    // Member functions
       void function_1();
       void function_2(double *mat);
       void function_3();
    
       void function_2_re_def(double *mat);
       void function_3_re_def();
    
    public:
       int rows;
       int cols;
    
       double *v1;
       double *v2;
    };
    The member functions, function_1 and function_2, perform the same task. They store some computed data in the array. I define function_1 as follows
    Code:
    void class_name::function_1()
    {
       v1=new(double[(rows+1)*(cols+1)]);
    
       double some_number;
    
       for(int i=1;i<=rows;i++){
          for(int j=1;j<=cols;j++){
             *(v1+i*(cols+1)+j)=some_number;
          }
       }
    }
    I define function_2 as
    Code:
    void class_name::function_2(double *mat)
    {
       mat=new(double[(rows+1)*(cols+1)]);
    
       double some_number;
    
       for(int i=1;i<=rows;i++){
          for(int j=1;j<=cols;j++){
             *(mat+i*(cols+1)+j)=some_number;
          }
       }
    }
    The only difference is that I want to pass an array to the function that does the same task instead of being limited as I am in function_1 which will only allow the operation to be performed on a single array. I want to be able to call function_1 or function_2 inside another function to do something else with the computed data. If I use function_1 inside this other function, called function_3, no problems arise.
    Code:
    void class_name::function_3()
    {
       // perform the computation, 
       function_1();
    
       // The data in v1 can be accessed inside this function
    
       // Print the data to screen
       for(int i=1;i<=rows;i++){
          for(int j=1;j<=cols;j++)
             cout<<*(v1+i*(cols+1)+j)<<" ";
          cout<<endl;
       }
    }
    However, I cannot get this to work if I use function_2, i.e. if I define function_3 as
    Code:
    void class_name::function_3()
    {
       // perform the computation, 
       function_2(v2);
    
       // The data in v2 cannot be accessed inside this function
    
       // Print the data to screen fails, program crashes
       for(int i=1;i<=rows;i++){
          for(int j=1;j<=cols;j++)
             cout<<*(v2+i*(cols+1)+j)<<" ";
          cout<<endl;
       }
    }
    What is more infuriating is that if I redefine function 2 by removing the call to new
    Code:
    void class_name::function_2_re_def(double *mat)
    {
       double some_number;
    
       for(int i=1;i<=rows;i++){
          for(int j=1;j<=cols;j++){
             *(mat+i*(cols+1)+j)=some_number;
          }
       }
    }
    and redefine function_3 as
    Code:
    void class_name::function_3_re_def()
    {
       // perform the computation, 
       v2=new(double[(rows+1)*(cols+1)]);
       function_2(v2);
    
       // The data in v2 can now be accessed inside this function
    
       // Print the data to screen 
       for(int i=1;i<=rows;i++){
          for(int j=1;j<=cols;j++)
             cout<<*(v2+i*(cols+1)+j)<<" ";
          cout<<endl;
       }
    }
    The program doesn't crash. I would like to know why the first version of function_3 with the call to function_2 crashes when called and why the second version, function_3_re_d ef with the dynamic memory allocation before the call to function_2_re_d ef, doesn't.

    Is there a scope issue that means that you must know the size of an array before passing arrays into class member functions?

    Thanks for your help.
  • weaknessforcats
    Recognized Expert Expert
    • Mar 2007
    • 9214

    #2
    This code:

    Code:
    void class_name::function_2(double *mat) 
    { 
       mat=new(double[(rows+1)*(cols+1)]); 
    etc...
    doesn't do what you think.

    mat is a local variable. It dies when the function completes. That is, mat is a copy of the original pointer.

    Now if you need to change the address inside the original pointer and have that change visible in other functions, then you will need to pass the address of the original pointer:

    Code:
    void class_name::function_2(double **mat) 
    { 
       *mat=new(double[(rows+1)*(cols+1)]);

    Comment

    • Oralloy
      Recognized Expert Contributor
      • Jun 2010
      • 988

      #3
      At the risk of being cheeky, how about passing as a reference to a pointer?

      Code:
      void class_name::function_2(double *&mat)
      {
        mat = new double[(rows+1)*(cols+1)]
      Then you can have happily confusing code that transparently assigns the outer pointer value.

      BTW, this sort of memory management is interesting, but I would think that STL vectors are a much better choice in most instances.

      Comment

      • weaknessforcats
        Recognized Expert Expert
        • Mar 2007
        • 9214

        #4
        You may pass a reference to a pointer.

        What you save is making the copy of the pointer. However, underneath, the compiler implements a reference by using a pointer. That means you save nothing using a reference to a pointer.

        What you should be using is a handle. Once you have allocated memory and pass that pointer around, you can't tell when it's safe to delete the allocation. It would only be safe if the pointer was the last copy in the program.

        To keep track of the number of copies of the pointer you would need to implement reference counting.

        You might read the C/C++ Insights article on using handle classes.

        Comment

        • Oralloy
          Recognized Expert Contributor
          • Jun 2010
          • 988

          #5
          Yep.

          I'm really unsure of what emaghero is trying to achieve.

          If he wants reference counted dynamic arrays, he'll need to implement envelopes and include a reference count in the core object. Not difficult, actually, just tedious.

          @emaghero - what is it you actully are trying to achieve?

          Comment

          • emaghero
            New Member
            • Oct 2006
            • 85

            #6
            Thanks for the replies.

            Comment

            Working...