简体   繁体   中英

Dereferencing a pointer to an object inside its class

I have SquareMatrix defined as such

SquareMatrix.h

#ifndef SQUAREMATRIX_H
#define SQUAREMATRIX_H
#include "Matrix.h"
#include <vector>

class SquareMatrix : public Matrix
{
    public:
        SquareMatrix();
        SquareMatrix(std::vector<std::vector<long double> >);
        //~SquareMatrix();    //just in case there is dynamic memory explicitly used
        //convenient member functions exclusive to SquareMatrix
        bool isUpperDiagonalMatrix() const;
        static SquareMatrix identityMatrix(unsigned);
        void LUDecompose();
        SquareMatrix *Lptr, *Uptr, *Pptr; //should be initialized by LUDecompose before using
    protected:
        void validateData();
    private:

};

#endif // SQUAREMATRIX_H

and I am trying to set Lptr , Uptr (and maybe Pptr ) with a call to SquareMatrix::LUDecompose() . It is defined below:

void SquareMatrix::LUDecompose()
{
    unsigned rowCount = this->getRowCount();
    //initialize L to identityMatrix
    *this->Lptr = SquareMatrix::identityMatrix(rowCount);
    //initialize U to sparse matrix with the first row containing the sole non-zero elements
    std::vector<std::vector<long double> > UData(1, this->matrixData[0]);   //making first rowVector the first rowVector of this
    UData.insert(UData.end(), rowCount - 1, std::vector<long double>(rowCount,0)); //making all other rowVectors zero vectors
    *Uptr = SquareMatrix(UData);
    // attempting to perform LU decomposition
    for (unsigned j = 0; j < rowCount; j++)
    {
        long double pivot = Uptr->matrixData[j][j];
        //the pivot should be non-zero; throwing exception that should effectively cause function to return
        if (pivot == 0)
            throw MatrixArithmeticException(LU_DECOMPOSITION_FAILURE);
        for (unsigned k = j+1; k < rowCount; k++)
        {
            if (j == 0)
            {
                //using *this to compute entries for L,U
                this->Lptr->matrixData[k][j] = (this->matrixData[k][j])/pivot;   //setting columns of L
                long double multiplier = this->Lptr->matrixData[k][j];
                //setting row of U
                for (unsigned l = k; l < rowCount; l++)
                {
                    Uptr->matrixData[k][l] = (this->matrixData[k][l])-multiplier*(this->matrixData[0][l]);
                }
            }
            else
            {
                //using U to compute entries for L,U
                //same procedure as before
                this->Lptr->matrixData[k][j] = (Uptr->matrixData[k][j])/pivot;
                long double multiplier = this->Lptr->matrixData[k][j];
                for (unsigned l = k; l < rowCount; l++)
                {
                    Uptr->matrixData[k][l] -= multiplier*(Uptr->matrixData[0][l]);
                }
            }
        }
    }
}

Upon trying to test out this function, it throws a segmentation fault at me, with the last line being the first line where I attempt to manipulate Lptr .

I attempt to change the object pointed by Lptr , and I know that I will not be able to reference the function and set the pointer equal to that reference. In other words, my compiler (GNU GCC compiler) will not allow this->Lptr = &SquareMatrix::identityMatrix(rowCount); as it will throw an -fpermissive type error.

Note: SquareMatrix::identityMatrix(unsigned) is defined as:

SquareMatrix SquareMatrix::identityMatrix(unsigned size)
{
    std::vector<long double> rowVector(size, 0L);
    std::vector<std::vector<long double> > identityMatrixData;
    for (int i = 0; i < size; i++)
    {
        //setting the rowVector to zero-one vector
        rowVector[i] = 1L;
        if (i > 0) rowVector[i-1] = 0L;
        //pushing rowVector into identityMatrixData
        identityMatrixData.push_back(rowVector);
    }
    return SquareMatrix(identityMatrixData);
}

What do you think you CAN do about it?

I think I have two options:

  1. throw the object on the heap, and then try to set it with the function (that would seem useless as you are redefining the object you just defined by throwing it on the heap)
  2. get c++11 (or something similar)
  3. Make the function a helper function that returns a std::vector<SquareMatrix*> of size two (containing pointers to the two desired SquareMatrix values), and create a function that calls the helper function and sets Lptr , Uptr to the respective elements of the returned vector .

Are my options this limited??

*Uptr = SquareMatrix(UData); in LUDecompose() is the problem. You cannot set the pointer to an object that is being destroyed when the function returns. Then the pointer is a dangling pointer and whenever you attempt to use it, it'll segfault.

You need to do Uptr = new SquareMatrix(UData); . Then in your destructor, call delete Uptr; .

If you have access to C++11, you can use std::unique_ptr or any pointer containers/wrappers.

Examples of your options:

#include <memory>

class Matrix
{
    public:
        Matrix() {}
        virtual ~Matrix() {}
};

class SqMatrix : public Matrix  //using raw pointers. You must remember to delete your pointers.
{
    private:
        SqMatrix* UPtr = nullptr;

    public:
        SqMatrix() : Matrix() {}
        void InitPtrs() {delete UPtr; UPtr = new SqMatrix();}
        ~SqMatrix() {delete UPtr;}
};

class OMatrix : public Matrix //No need to worry about clean up.
{
    private:
        std::unique_ptr<OMatrix> OPtr;

    public:
        OMatrix() : Matrix() {}
        void InitPtrs() {OPtr.reset(new OMatrix());}
        ~OMatrix() {}
};

Another option is to just store it in a vector.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM