Thread: Creating and freeing dynamic arrays

  1. #1
    Registered User
    Join Date
    Feb 2008
    Posts
    28

    Creating and freeing dynamic arrays

    I am trying to write my own class Matrix that dynamically allocates two dimensional arrays and contains functions to perform addition, subtraction etc on objects of class Matrix. I have a few questions related to dynamic arrays:
    1. Must an array dynamically allocated using new be freed by delete? If a temporary object of class Matrix is declared within a function, will the memory be freed every time the function returns?
    2. I have written my program (could provide code if needed) without any destructors at all. Would I face any trouble later since allocated memory has not been freed? I have also overloaded the "=" operator so that a statement involving objects like:
    Code:
    a=b;
    Will result in the dynamic array in object "a" to be allocated using new with respect to the rows and columns of "b". The function is:
    Code:
    // Assigning one matrix to another.
    	Matrix operator=(const Matrix &mat2) {
    		int x, y;
    		dimension_check(mat2);
    /*		for (x=0;x<rows;x++) {
    			delete [] mat_var[x];
    		}
    		delete [] mat_var; */
    		rows=mat2.rows;
    		columns=mat2.columns;
    		create_matrix();
    		for (x=0;x<mat2.rows;x++) {
    			for (y=0;y<mat2.columns;y++) {
    				mat_var[x][y]=mat2.mat_var[x][y];
    			}
    		}
    		return *this;
    	}
    Please note that part where delete [] has been commented out. The program woks only with these commented. However, the program also works when a Matrix that has been initially allocated as 2*2 is equated to a matrix of 3*1. I have the feeling I am doing something fundamentally wrong by reallocating without any delete [] statement after reading some of the previous posts in this forum. People recommend allocating new memory, copying and then deleting new memory. However, if by equating a=b, it is implied that the contents of "a" are not needed, then could a copy be skipped? But to allocate new dimensions of memory would a delete not be required?
    The function create_matrix() is:
    Code:
    	void create_matrix() {
    		try {
    			mat_var=new float *[rows];
    		}
    		catch (std::bad_alloc xa) {
    			std::cout << "Out of memory.\n";
    			exit(1);
    		}
    		int row_count;
    		for (row_count=0;row_count<rows;row_count++) {
    			try {
    				mat_var[row_count]=new float [columns];
    			}
    			catch (std::bad_alloc xa) {
    				std::cout << "Out of memory.\n";
    				exit(1);
    			}
    		}
    		return;
    	}
    Thanks.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    1. Must an array dynamically allocated using new be freed by delete?
    Yes, but of course you must match new[] with delete[], not delete.

    If a temporary object of class Matrix is declared within a function, will the memory be freed every time the function returns?
    Yes, assuming the Matrix destructor is written correctly.

    2. I have written my program (could provide code if needed) without any destructors at all. Would I face any trouble later since allocated memory has not been freed?
    Maybe.

    However, if by equating a=b, it is implied that the contents of "a" are not needed, then could a copy be skipped?
    No, you have to copy otherwise you have two Matrix objects that share the same content.

    You should implement the copy constructor, destructor and swap member function, upon which you can implement the copy assignment operator as:
    Code:
    Matrix& operator=(const Matrix &mat2) {
        Matrix temp(mat2);
        swap(temp);
        return *this;
    }
    
    // or
    
    Matrix& operator=(const Matrix &mat2) {
        if (this != &mat2) {
            Matrix temp(mat2);
            swap(temp);
        }
        return *this;
    }
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by laserlight View Post
    You should implement the copy constructor, destructor and swap member function, upon which you can implement the copy assignment operator as:
    Code:
    Matrix& operator=(const Matrix &mat2) {
        Matrix temp(mat2);
        swap(temp);
        return *this;
    }
    
    // or
    
    Matrix& operator=(const Matrix &mat2) {
        if (this != &mat2) {
            Matrix temp(mat2);
            swap(temp);
        }
        return *this;
    }
    The second of those (with a test of this) should be used with extreme caution, as it will behave in unexpected ways in some circumstances (eg if Matrix supplies an operator&()). However, if the limitations are allowed for, it is a useful performance optimisation.

  4. #4
    Registered User
    Join Date
    Feb 2008
    Posts
    28
    Thanks for the responses. I included the copy constructor and a destructor in my class declaration. The program works fine. One more question:
    I have the following constructors in my class declaration:
    Code:
    	Matrix() {
    		rows=0;
    		columns=0;
    		mat_var=0;
    	}
    	Matrix(int x,int y) {
    		rows=x;
    		columns=y;
    		create_matrix();
    	}
    	Matrix(int x) {
    		rows=x;
    		columns=1;
    		create_matrix();
    	}
    	Matrix(const Matrix &mat1) {
    		int x, y;
    		rows=mat1.rows;
    		columns=mat1.columns;
    		create_matrix();
    		for (x=0;x<rows;x++) {
    			for (y=0;y<columns;y++) {
    				mat_var[x][y]=mat1.mat_var[x][y];
    			}
    		}
    	}
    The first constructor is an empty default constructor. Initially I had not added the mat_var=0 statement. I find that without it the program seg faults. And it does not even display the usual "Segmentation fault" error but gives me errors related to glibc and stack trace. Why is that so? Is it because the pointer points to some random location and when this constuctor is used, objects have unusable pointers.

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    The first constructor is an empty default constructor. Initially I had not added the mat_var=0 statement. I find that without it the program seg faults.
    Chances are they were initialised to garbage.

    Incidentally, you probably want rows and columns to be unsigned int. Then you can implement your default constructor as:
    Code:
    Matrix(unsigned int x = 0, unsigned int y = 0) : rows(x), columns(y) {
        create_matrix();
    }
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by circuitbreaker View Post
    And it does not even display the usual "Segmentation fault" error but gives me errors related to glibc and stack trace. Why is that so? Is it because the pointer points to some random location and when this constuctor is used, objects have unusable pointers.
    Because it's called undefined behavior! Anything can happen, in other words.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #7
    Registered User
    Join Date
    Feb 2008
    Posts
    28
    Code:
    Matrix(unsigned int x = 0, unsigned int y = 0) : rows(x), columns(y) {
    Would the above code be equivalent to
    Code:
    Matrix(unsigned int x = 0, unsigned int y = 0) {
    rows=x;
    columns=y;
    Why is it written like that?

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    It is. It's the initializer list. The biggest change is that it basically calls the constructor. For built-in types, it probably won't matter, but for objects, it can matter. If you put it in the body, it will call the default constructor first and then the assignment operator, but if you put it in the initializer list, it will call the appropriate constructor only.
    It's recommended to use initializer lists, if possible.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #9
    Registered User
    Join Date
    Feb 2008
    Posts
    28
    Thanks Laserlight, Elysia and Grumpy.

Popular pages Recent additions subscribe to a feed