2D-Array bekannter Größe als Call by Reference an Memberfkt. übergeben



  • Hallo Zusammen,

    ich möchte ein Array bekannter Größe innerhalb einer Memberfunktion bearbeiten, daher soll selbiges Call by Reference übergeben werden.

    Ich habe viele Varianten getestet, den ganzen Tag gegooglet, etc., letztendlich scheitert es an der Übergabe. Die hier gezeigte Variante funktioniert natürlich nicht, weil kein einfacher float sondern ein 2D-Array übergeben bzw. innerhalb der Fkt. zur Bearbeitung zur Verfügung stehen soll. Aber wie löse ich das nun am einfachsten?

    Hier mein Code (nicht relevanter Code wurde entfernt):

    /* Projekt.cpp */
    #include <iostream>   // Ein- und Ausgabebibliothek
    
    using namespace std;  
    
    class RingPuffer {
    	public:
    		RingPuffer(unsigned int p_aryLgthRead, unsigned short p_multLgth, string p_filePath);	
    		void Fill(float &Ary);
    	private:
    		unsigned int aryLgthRead;
    		unsigned short multLgth;
    		string filePath;
    };
    
    RingPuffer::RingPuffer(unsigned int p_aryLgthRead, unsigned short p_multLgth, string p_filePath) {
    	aryLgthRead = p_aryLgthRead;
    	multLgth    = p_multLgth;
    	filePath    = p_filePath;
    }
    
    void RingPuffer::Fill(float &Ary) {
    	cout << "Fülle Ringpuffer.." << endl;
    	// Array-Bearbeitung
    }
    
    int main() {     
    	unsigned int p_aryLgthRead = 10;
    	unsigned short p_multLgth = 5;
    	string p_filePath = "blubb";
    
    	RingPuffer testRingPuffer(p_aryLgthRead, p_multLgth, p_filePath); 
    
    	float ringPufferArray[2][p_aryLgthRead*p_multLgth];
    	testRingPuffer.Fill(ringPufferArray);
    
    	// Programmende
    	return 0;            
    }
    

    Man sagte mir, dass man auch Vektoren benutzen kann, darauf würde ich gerne verzichten. Für eine kleine Erklärung (ich arbeite noch nicht so lange mit C++ bzw. bin nur mit einigen Grundlagen vertraut) zu einer funktionierenden Lösung wäre ich ebenfalls sehr sehr dankbar.

    Vielen Dank schonmal!!



  • Hi.

    Bekanntes Anfängerproblem. Zuerst sei mal klargestellt, dass ein 2 Dimensionales Feld kein ** (Doppelzeiger) ist. Das wird oft falsch vermittelt.

    Um ein Feld mit völlig beliebiger Grösse auszugeben, kommst du nicht darum herum die Dimensionen mitanzugeben.

    void out (int* a, int val1, int val2)
    {
    	for (int i = 0; i < val1; i++)
    	{
    		for (int y = 0; y < val2; y++)
    			std::cout << a[i*val2+y];
    		std::cout << std::endl;
    	}
    }
    

    Jedoch kann, wenn zu compile Zeit die 2 Dimension bekannt ist ein wenig reduziert werden.

    void out2 (int a[][3], int val)
    {
    	for (int i = 0; i < val; i++)
    	{
    		for (int y = 0; y < 3; y++)
    			std::cout << a[i][y];
    		std::cout << std::endl;
    	}
    }
    

    Völlig banal ist die Sache, wenn beide Dimensionen zur Compile Zeit bekannt sind:

    void out3 (int a[5][3])
    {
    	for (int i = 0; i < 5; i++)
    	{
    		for (int y = 0; y < 3; y++)
    			std::cout << a[i][y];
    		std::cout << std::endl;
    	}
    }
    

    Die aufrufe könnten dann so aussehen:

    int v[5][3];
    
    	for (int i = 0; i < 5; i++)
    		for (int y = 0; y < 3; y++)
    			v[i][y] = i+y;
    
    	out (v[0],5,3);
    	out2 (v, 3);
    	out3 (v);
    

    Per Referenzen ist das so nicht möglich, da du darauf angewiesen bist auf die anderen Elemente, die Folgen zuzugreifen.

    btw:
    Kannst du mir sagen, wie du das zum laufen gebracht hast? 😉

    float ringPufferArray[2][p_aryLgthRead*p_multLgth];
    


  • drakon schrieb:

    Hi.
    Bekanntes Anfängerproblem. Zuerst sei mal klargestellt, dass ein 2 Dimensionales Feld kein ** (Doppelzeiger) ist. Das wird oft falsch vermittelt.

    Hat jemand etwas von Doppelzeigern geschrieben?
    Doppelzeiger gibt es btw. auch gar nicht, wenn dann Zeiger auf Zeiger.



  • drakon schrieb:

    Per Referenzen ist das so nicht möglich, da du darauf angewiesen bist auf die anderen Elemente, die Folgen zuzugreifen.

    Natürlich kann man auch Referenzen auf Arrays übergeben. Das hat ggü. out3 auch den großen Vorteil, dass die erste Dimension nicht auf einen Zeiger heruntergebrochen wird. Bei out3 kannst Du nämlich ein beliebiges int[][3] übergeben, bei out4 nicht.

    void out4( float (&array) [5][6] )
    {
    }
    

    Noch interessanter wird das ganze, wenn man die Funktion für Arrays beliebiger Größe generisch schreibt (und die Dimensionen deduzieren lässt).

    template< size_t N, size_t M >
    void out4( float (&array) [N][M] )
    {
    }
    


  • Guten Morgen.

    In der Tat, die Lösung von LordJaxom funktioniert, allerdings nur eingeschränkt. Es wird ja vorrausgesetzt, dass in der Funktionsdeklaration die Array-Dimensionen mit angegeben werden (hier 5x6). Diese werden bei mir allerdings erst in der main-Methode defininiert, so dass selbige in der Klassendeklaration noch unbekannt sind. Erst bei Objekterzeugung werden selbige festgelegt.

    Nunja, erst durch den Konstruktor sind die Dimensionen ja als private-Eigenschaften des erzeugten Objekts festgelegt. Wie kann ich das am geschicktesten lösen?



  • CClass::CClass( int iErsteDim, int iZweiteDim, /* Weitere  Parameter ...*/ ) {
    
        m_2DArray = new VariablenTyp[ iErsteDim ][ iZweiteDim ];
    }
    

    Ob das jetzt so funktioniert wie ich mir das gedacht habe, hab ich net getestet *g*. Versuchs halt.

    Gruß Tobi.



  • T0bi: Ich verstehe nicht ganz, wie ich die von Dir beschriebene Lösung umsetzen soll. Sowohl in der main-Methode als auch innerhalb des Konstruktors ein Array anlegen? Und dann? 😕

    Die allerbeste Lösung wäre diejenige, dass man einfach nur den Konstruktor mit den den Parametern aufruft (sprich Arraygrößen) und dass man danach eine Memberfunktion des erzeugten Objekts aufruft, welche ein Array zurückgibt. Aber das stelle ich mir noch weitaus schwieriger vor, als meine Implementierung, in der einfach ein "fertiges" Array weiter bearbeitet wird.



  • Naja... du deklarierst eine Membervariable in deiner Klasse die auf ein 2D-Array verweisen soll. Dies sollte ein Doppelpointer sein z.B. void **m_pArray;

    Gruß Tobi.



  • Hier mal nen Beispiel:

    class CClass {
    
        private:
    
            int    **m_p2DArray;
    
        public:
    
            CClass( );
            CClass( int iFirstDim, int iSecondDim, int iInitial );
            ~CClass( );
    
            int       GetValue( int iFirstDim, int iSecondDim ) const;
    
    };
    
    // ***** Default constructor *****
    CClass::CClass( ) {
    
        m_p2DArray = 0;
    }
    
    // ***** (1) constructor *****
    CClass::CClass( int iFirstDim, int iSecondDim, int iInitial ) {
    
        // ***** Allocate some memory *****
        m_p2DArray = new int*[ iFirstDim * sizeof( int ) ];
    
    	for( int i = 0; i < iFirstDim; i++ )
    		m_p2DArray[ i ]= new int[ iSecondDim * sizeof( int ) ];
    
        // ***** Initial array *****
        for( int y = 0; y < iSecondDim; y++ ) {
    
            for( int x = 0; x < iFirstDim; x++ ) {
    
                m_p2DArray[ x ][ y ] = iInitial;
            }
        }       
    }
    
    // ***** Destructor *****
    CClass::~CClass( ) {
    
        free( m_p2DArray );
    }
    
    // ***** Get value *****
    int CClass::GetValue( int iFirstDim, int iSecondDim ) const {
    
        return m_p2DArray[ iFirstDim ][ iSecondDim ];
    }
    
    int main( ) {
    
        CClass foo( 5, 5, 1 );
    
        cout << foo.GetValue( 2, 1 ) << endl;
        getchar( );
    	return 0;
    }
    


  • Selbst wenn du im Destruktor statt free delete benutzt hättest, wie es sich gehört, hättest du da ein schönes Speicherleck. Und warum nicht std::vector?



  • Wieso hat er dann nen Speicherleck? Wird etwa nicht alles wieder freigegeben?

    Gruß Tobi.



  • T0bi schrieb:

    Wieso hat er dann nen Speicherleck?

    Weil du iFirstDim+1-mal new aufrufst, aber nur einmal delete?



  • Hmm dann müsste er es mit einer For-Schleife alles deleten?



  • T0bi schrieb:

    Hmm dann müsste er es mit einer For-Schleife alles deleten?

    Ganz einfache Regel: Für jedes new/new[] muss auch ein korrespondierendes delete/delete[] aufgerufen werden.





  • Ich hab gelernt, das man 2d arrays garnicht mit new erstellen kann... stattdessen kann man die spalten "hintereinander" hängen... damit würde sich zumindest die Frage klären wie man 2d-arrays deletet: garnicht



  • Merker++ schrieb:

    drakon schrieb:

    Hi.
    Bekanntes Anfängerproblem. Zuerst sei mal klargestellt, dass ein 2 Dimensionales Feld kein ** (Doppelzeiger) ist. Das wird oft falsch vermittelt.

    Hat jemand etwas von Doppelzeigern geschrieben?
    Doppelzeiger gibt es btw. auch gar nicht, wenn dann Zeiger auf Zeiger.

    Gar niemand. (zumindes bis zu deinem Post). Aber Doppelzeiger werden (wie jetzt auch bereits) sehr gerne mit 2D Array in Verbindung gebracht, welche so direkt nichts miteinander zu tun hat. (Jah man KANN 2D Arrays und Doppelpointer benutzen, aber bei seinem Fall ist das wahrscheinlich nicht erwünscht).

    Du hast die Antwort bereits geschrieben. Mit einer Schlaufe. Irgendwo habe ich das hier mal mit einem dynamischen 3D Array gemacht. (Sieht grauenhaft aus und std::vector sollte da eher benutzt werden).

    Ich hab gelernt, das man 2d arrays garnicht mit new erstellen kann... stattdessen kann man die spalten "hintereinander" hängen... damit würde sich zumindest die Frage klären wie man 2d-arrays deletet: garnicht

    Richtig. Im herkömmlichen Sinne ist es nicht möglich dynamsich ein 2D Array zu erstellen. Jedoch ist das, was du vorschlägst ("hintereinanderlegen") genau das, was der Compiler so oder so auch bei 2D Arrays macht.
    Das mit dem deleten stimmt nicht. Man muss die genau gleich, wie alles anderen deleten. Wenn man da hald in einer Schlaufe Speicher per new anfordert, dann muss man den hald auch wieder mit delete in einer Schlaufe freigeben.

    EDIT:
    Hier war das mit dem 3D Array:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-211534-and-highlight-is-.html

    btw. Die Forensuche hier ist ***.. 🙄



  • klar muss man die normalen arrays wieder deleten, jedoch stellt sich die frage nicht mehr wie man 2d-arrays deleten soll, es lässt sich auf einen langen array beschränken, der einfach mit delete[] freigegeben wird


Anmelden zum Antworten