2D Matrix und Funktionsobjekt - Operator[]



  • hi

    Ich hab eine etwas seltsame Fehlermeldung

    error C2678: binary '[' : no operator found which takes a left-hand operand of type 'const Matrix2D' (or there is no acceptable conversion)
    could be 'int *Simple2DimArr::operator [](int)'
    while trying to match the argument list '(const Matrix2D, int)'

    bei folgendem Code. (Die Simple2DimArr Klasse hab ich aus der FAQ)

    class Simple2DimArr
    {
        private:
            int* pArr;
            int Rows, Cols;
        public:
            Simple2DimArr(int Zeilen, int Spalten)
            {
                Rows = Zeilen;
                Cols = Spalten;
                pArr = new int[Rows * Cols];
            }
            int* operator[](int Zeile)
            {
                return & pArr[Zeile * Cols];
            }
            ~Simple2DimArr()
            {
                delete [] pArr;
            }
    };
    
    typedef Simple2DimArr Matrix2D;
    
    struct distance_compare
    {
    	int source_;
    	const Matrix2D& distance_;
    	distance_compare( int source, const Matrix2D& distance )
    		: source_( source ), distance_( distance ){}
    	bool operator()( const int& lhs, const int& rhs )
    	{
    		return distance_[source][lhs] > distance_[source][rhs];  // <--- In diese Zeile springt der Debugger
    	}
    };
    
    //Anwendung
    int main()
    {
        {   // Testblock
    		Matrix2D distance(3,3);
    		distance[0][0] = 0; 
    		distance[0][1] = 1; 
    		distance[0][2] = 2; 
    		distance[1][0] = 1; 
    		distance[1][1] = 0; 
    		distance[1][2] = 1; 
    		distance[2][0] = 2; 
    		distance[2][1] = 1; 
    		distance[2][2] = 0; 
    
    		std::cout << distance[1][1] << std::endl;
    	} 
    	return 0;
    }
    // getestetes Minimalbsp.
    

    Wenn ich die struct distance_compare auskommentiere gehts.

    Hat jemand vielleicht einen Tipp für mich?
    Wäre super 🙂



  • Edit:
    ..in Zeile 33 sollte es natürlich heissen

    return distance_[source_][lhs] > distance_[source_][rhs];
    


  • Hab das Problem eingeengt.
    Wenn ich beim Member von distance_compare

    const Matrix2D& distance_;
    

    das const und die Referenz (&) weglasse, kompiliert er obiges Beispiel ohne Murren und gibt 0 aus.
    Das Problem ist halt, das ich distance_compare in STL Algorithmen als Vergleichsoperator brauche.
    Und dabei gibts ein Assert von "_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)", schätze mal, dass der Array der 2DMatrix (int Zeiger) beim kopieren in den Algorithmus flöten geht.
    Wie kann ich dem entgegenwirken?

    ps: code mit dem ich das getestet habe

    int source = 1;
    		distance_compare comp_1( source, distance );
    		std::priority_queue< int, std::vector<int>, distance_compare > pqueue_1( comp_1 );
    		for( int i = 0; i < 3; ++i ) {
    		    pqueue_1.push( distance[source][i] );
    		}
    		std::cout << pqueue_1.top() << std::endl;
    		pqueue_1.pop();
    		std::cout << pqueue_1.top() << std::endl;
    		pqueue_1.pop();
    		std::cout << pqueue_1.top() << std::endl;
    		pqueue_1.pop();
    


  • deine struct distance_compare hat ein member const Matrix2D

    dadurch kannst du nur Funktionen aufrufen, die auch als const deklariert sind bei deiner klasse.
    also noch dazuügen:

    // in die Klasse
    const int* const operator[](int Zeile) { return ....} const;
    


  • Hm, dann kann ich aber nicht mehr die Werte zuweisen.
    Lass ich das erste const weg, geht zwar die Zuweisung, aber beim Vergleichen kommt ein Fehler:

    Unhandled exception at 0x00417861 in Test.exe: 0xC0000005: Access violation reading location 0xfbcefb20.

    Habe das Gefühl, ich such im leeren Raum.. 😕



  • naja, du hast eben eine const-funktion und eine nicht-konst-fuktion. Der compiler nimmt dann die, die er gerade brauch. Lass beide drin, dann müsts doch gehn



  • *freu*
    Mir is grad der Knoten aufgegangen 💡
    Stichwort: Assignable für Klassen mit Zeigern und Arrays
    Hab dem 2D-Array nen ordentlichen Copyconstructor und operator= verpasst, der mir auch den Array Inhalt korrekt kopiert.
    @Maxi
    Das geht auch nicht, der Assert kommt wieder. Aber trotzdem Danke! Das const und die Referenz vom Member distance_ sind nun nicht mehr nötig, und alle Aktionen sind nun auch in STL Algorithmen verfügbar.

    Hier nochmal die aktuelle Version:

    class Simple2DimArr
    {
        private:
            int* pArr;
            int Rows, Cols;
        public:
            Simple2DimArr(int Zeilen, int Spalten)
            {
                Rows = Zeilen;
                Cols = Spalten;
                pArr = new int[Rows * Cols];
            }
    		Simple2DimArr( const Simple2DimArr& other )
    		{
    			Rows = other.Rows;
    			Cols = other.Cols;
    			pArr = new int[Rows * Cols];
    			for( int i = 0; i < Rows * Cols; ++i ) {
    				pArr[i] = other.pArr[i];
    			}			
    		}
    		Simple2DimArr operator=( const Simple2DimArr& other )
    		{
    			Rows = other.Rows;
    			Cols = other.Cols;
    			pArr = new int[Rows * Cols];
    			for( int i = 0; i < Rows * Cols; ++i ) {
    				pArr[i] = other.pArr[i];
    			}
    			return *this;
    		}
            int* operator[](int Zeile)
            {
                return & pArr[Zeile * Cols];
            }
            ~Simple2DimArr()
            {
                delete [] pArr;
            }
    };
    
    typedef Simple2DimArr Matrix2D;
    
    ////compare funktions objekt
    struct distance_compare
    {
    	int source_;
    	Matrix2D distance_;
    	distance_compare( int source, const Matrix2D& distance )
    		: source_( source ), distance_( distance ){}
    	bool operator()( const int& lhs, const int& rhs )
    	{
    		return distance_[source_][lhs] > distance_[source_][rhs];
    	}
    };
    
    int main()
    {
        {   // Testblock
    		Matrix2D distance(3,3);
    		distance[0][0] = 0; 
    		distance[0][1] = 1; 
    		distance[0][2] = 2; 
    		distance[1][0] = 1; 
    		distance[1][1] = 0; 
    		distance[1][2] = 1; 
    		distance[2][0] = 2; 
    		distance[2][1] = 1; 
    		distance[2][2] = 0; 
    		std::cout << distance[1][1] << std::endl;
    
    		//Priority Queue
    		int source = 0;
    		distance_compare comp_1( source, distance );
    		std::priority_queue< int, std::vector<int>, distance_compare > pqueue_1( comp_1 );
    		for( int i = 0; i < 3; ++i ) {
    		    pqueue_1.push( distance[source][i] );
    		}
    		std::cout << pqueue_1.top() << std::endl;
    		pqueue_1.pop();
    		std::cout << pqueue_1.top() << std::endl;
    		pqueue_1.pop();
    		std::cout << pqueue_1.top() << std::endl;
    		pqueue_1.pop();
    	}   // Testblock
    	return 0;
    }
    

    Für Verbesserungsvorschläge wär ich natürlich auch sehr dankbar. 🙂



  • vergiss beim operator= nich, noch dedn alten speicher zu deleten


Log in to reply