Wie Konstruktor bauen - brauche Pointer



  • Was soll das ganze denn werden? Du legst dir erst eine Dummy-Matrix an, die dann die "echte" Matrix initialisieren soll. Pack lieber den gesamten Quelltext aus der Init_Matrix() in den Klassenkonstruktor, das ist einfacher zu handhaben.



  • Danke euch,

    leider stehe ich irgendwie auf dem Schlauch momentan. Ich versuche es so,
    aber so wid doch A uninitialisiert verwendet.

    template<class T>  Matrix<T>::Matrix(Matrix<T>* A)
    {
    	A->num_procs = 1;
    	A->my_id = 0;
    	A->my_nbr_cols = 0;
    	A->my_start_index = 0;
    	A->n = 0;
    	A->all_nbr_cols = NULL;
    	A->start_indices = NULL;
    	A->my_nnz = 0;
    	A->pe = NULL;
    	A->symmetric = false;
    }
    
    template <class T> 	Matrix<T>* 	
    Matrix<T>::New_Matrix()
    {
    	Matrix<T> *A = new Matrix<T>(A);
    // 	Init_Matrix(A);
    
    	return A;
    }
    

    Wenn ich es so mache muss ihc ja wieder ein Objekt auf dem stack anlegen um dann ein Objekt auf dem Heap zu alloziieren:

    emplate<class T>  Matrix<T>::Matrix()
    {
    	num_procs = 1;
    	my_id = 0;
    	my_nbr_cols = 0;
    	my_start_index = 0;
    	n = 0;
    	all_nbr_cols = NULL;
    	start_indices = NULL;
    	my_nnz = 0;
    	pe = NULL;
    	symmetric = false;
    }
    
    template<class T> Matrix<T>::~Matrix()
    {
    
    }
    
    template <class T> 	Matrix<T>* 	
    Matrix<T>::New_Matrix()
    {
    	Matrix<T> *A = new Matrix<T>();
    // 	Init_Matrix(A);
    
    	return A;
    }
    
    //Aufruf
    Matrix<double>* A = New_Matrix() //geht nicht
    Matrix<double>* A = o_matrix.New_Matrix() //geht
    

    Könnt ihr mir vielleicht einen Anstoß geben?

    Danke



  • Wozu brauchst du überhaupt die New_Matrix()-Methode? Du hast doch den Matrix-Ctor, der alles nötige erledigt:

    Matrix<double>* A = new Matrix<double>();
    

    (btw, was spricht dagegen, die Matrix auf den Stack zu packen?)



  • Ah ok,

    dann hätte ich aber noch eine Frage.
    Wenn ich eine Methode aufrufen will die in einer Klasse ist, dazu muss ich dann aber schon immer ein Objekt auf dem stack anlegen oder?

    also so:

    Matrix<T>::print()
    {
          //irgendwas
    }
    
    //beim aurufen:
    Matrix<double> o_matrix;
    
    o_matrix.print();
    

    Ist das so in Ordnung?



  • Wenn du eine Methode aufrufen willst, brauchst du ein Objekt, auf das du dich beziehen kannst - wo das liegt, ist egal:

    //Objekt auf dem Stack:
    Matrix o;
    o.print();
    
    //Objekt auf dem Heap:
    Matrix* p = new Matrix;
    p->print();
    

    Ausnahme sind statische Methoden (in der Klassendefinition als 'static typ func(...);' angegeben), die kannst du auch ohne ein zugehöriges Objekt per "Matrix::create();" aufrufen.



  • Danke,

    jetzt bekomme ich aber einen haufe an segfaults.
    Folgender Code:

    Index_Set::Index_Set()
    {
    
    }
    
    Index_Set::Index_Set(int len)
    {
    	idcs = NULL;
    	len = len;
    	idcs = new int[len];
    }
    
    Index_Set::~Index_Set()
    {
    
    }
    
    //Index_Set.h
    		///Ctor
    		Index_Set();
    		Index_Set(int len);
    
    		///Dtor
    		~Index_Set();
    
    		//Member variables
    		///The index set array
        	int 	*idcs; 
    
    		///Lenght of the index set
    		int		len;
    

    wird so benutzt:

    // Extract pattern from pattern matrix  
    	// Create the Index Set J
    	J_pattern = o_sub.Get_J_Set(P, col);
    	// Copy the values into the big working Index_Set J
    	memcpy(J->idcs, J_pattern->idcs, J_pattern->len * sizeof(int));
    	J->len = J_pattern->len;
    

    und in Get_J_Set(P,col) folgendes

    template <class T> 	Index_Set* 	
    Spai_Sub<T>::Get_J_Set(	Pattern	 	*P,
    					const int 	col)
    {
    	Index_Set	*J = NULL;
    	J = P->j_sets[col];	
    	return J;
    }
    
    das pattern wird so gefüllt:
    [cpp]
    for( int col = 0; col < n; col++)
    	{
    		i_set = new Index_Set(1);
    		i_set->idcs[0] = col;
    		P->j_sets[col] = i_set;
    	}
    

    [/cpp]



  • achja,
    J und J_pattern sind natürlich schon initialisiert vorher:

    Index_Set 	o_is,
     				*J_pattern = NULL,
     				*J = NULL, 
    				*I = NULL;
    
    	// J will be filled with the
    	// new J values from pattern
    	// and will be updated each augmenting 
    	// step.
    	J = new Index_Set(A->n);	
           // Extract pattern from pattern matrix  
    	// Create the Index Set J
    	J_pattern = o_sub.Get_J_Set(P, col);
    	// Copy the values into the big working Index_Set J
    	memcpy(J->idcs, J_pattern->idcs, J_pattern->len * sizeof(int));
    	J->len = J_pattern->len;
    

    und das Pattern hat sowas als Member:

    /// All index sets of each column
        	Index_Set 	**j_sets;
    
    		/// The length of the pattern - always size n of
    		/// matrix A
    		int 		len;
    


  • Woher kommt eigentlich P und wie wurde es angelegt?

    (btw, hast du früher mal mit Java gearbeitet?)



  • Ne hab wenig mit Java gemacht.

    P wird so angelegt:

    Pattern::Pattern(int len)
    {
    	j_sets = NULL;
    	len = len;
    	j_sets = new Index_Set*[len];	
    }
    
    P = new Pattern(n);
    


  • Es liegt irgendwie am memcpy...ich weiß nicht warum...



  • Und wo genau kommt der Segfault? (ich würde ja darauf tippen, daß die Größenangaben nicht ganz zusammenpassen)

    PS Nur am Rande: In C++ verwendet man Pointer eher selten - wenn machbar, solltest du deine Variablen auf dem Stack unterbringen. Und die Zugriffe auf Membervariablen sollten lieber von der Klasse selbst übernommen werden.



  • Nene - an den Längen kanns nicht liegen - es hat ja alles funktioniert bis ich jetzt den Konstruktor geändert hatte. An den Längen hab ich nix verändert.

    Der segfault kommt genau beim memcpy() und schreit so:

    Conditional jump or move depends on uninitialised value(s)
    ==7389==    at 0x4022E6C: memcpy (mc_replace_strmem.c:406)
    ==7389==    by 0x804A1CE: Sp<double>::SP_Column(Matrix<double>*, Matrix<double>*&, Pattern*, int, double, int, int) (in /Source_code/Current/bin/sp)
    ==7389==    by 0x80497D2: main (in /Source_code/Current/bin/sp)
    

    Hmm....



  • Ich tippe immer noch auf eine Index-Überschreitung oder einen nicht-initialisierten Zeiger.

    Vorschlag: Erklär mal, was du überhaupt vorhast. Vielleicht wird der Quelltext dann klarer. (btw, anstelle der nackten Zeiger würde ich lieber mit std::vector<> arbeiten)



  • Ja ich weiß dass es in C++ schöne Templates gibt wie vector oder Set. Aber ich brauche wirklich das hier.

    Was ich vorhabe ist eigentlich trivial: Ein array in ein anderes kopieren.

    Also ich habe 2 Index_Sets und möchte von dem einen Index_Set->idcs array die werte in das andere kopieren Index_Set->idcs.

    Das erste wird so initialisiert dass es vom Pattern welches ein array aus Index_Sets hat einfach eine Index_Set extrahiert wird und an J_pattern übergeben wird.
    J (also das zweite array wohin kopiert werden soll) wird einfach so initialisiert:

    Index_Set* J = new Index_Set(n);

    J_pattern wird so gefüllt:

    template <class T>     Index_Set*    
    Spai_Sub<T>::Get_J_Set(    Pattern         *P,
                        const int     col)
    {
        Index_Set    *J = NULL;
        J = P->j_sets[col];   
        return J;
    }
    

    Das Pattern füllt seine j_sets so:

    Pattern 	*P = new Pattern(n);
    
    	for( int col = 0; col < n; col++)
    	{
    		i_set = new Index_Set(1);
    		i_set->idcs[0] = col;
    		P->j_sets[col] = i_set;
    	}
    

    wobei der Konstruktor so aussieht:

    Pattern::Pattern(int len)
    {
    	j_sets = NULL;
    	len = len;
    	j_sets = new Index_Set*[len];	
    }
    

    Die Member von Pattern:

    /// All index sets of each column
        	Index_Set 	**j_sets;
    
    		/// The length of the pattern - always size n of
    		/// matrix A
    		int 		len;
    

    das ganze wird so aufgerufen:

    Index_Set 	/*o_is,*/
     				*J_pattern = NULL,
     				*J = NULL, 
    				*I = NULL;
    
    	J = new Index_Set(A->n);		
    
    	J_pattern = o_sub.Get_J_Set(P, col);
    
    	// Copy the values into the big working Index_Set J
    	memcpy(J->idcs, J_pattern->idcs, J_pattern->len * sizeof(int));
    	J->len = J_pattern->len;
    


  • Woher kommen denn die Größenangaben n und l?

    (und was genau spricht dagegen, vector'en anstelle der dynamischen Arrays zu verwenden?)



  • das l ist eine eins als "1".

    das n ist gesetzt. Ich habe es gerade ausgeben lassen.

    Ich benutze keine std::vectoren aus einem Grund der vielleicht lächerlich erscheint - aber ich arbeite an einem zeitperformanten programm - und ich hatte mit der std-lib schon einige probleme damals gehabt die mein programm unglaublich langsam werden ließen. Ich hatte es damals umgeschrieben auf reine pointer-arithmetik ohne std-lib und es war viel schneller. Der ein oder andere mag jetzt sagen: Jaja-das lag wohl eher an der umschreibung und nicht an der std-lib. Mag sein - aber nochmal will ich mir das nicht antun. Soviel dazu.



  • ok, es liegt definitiv daran das J_pattern->len nicht gesetzt ist.
    Aber warum?



  • Lass dir doch mal J_Pattern->len und J->len ausgeben



  • AAAArgh.

    Ja klar, sowas geht ja nicht:

    Index_Set::Index_Set(int len)
    {
    	idcs = NULL;
    	len = len;
    	idcs = new int[len];
    }
    

    sondern nur sowas 🙂

    Index_Set::Index_Set(int len_a)
    {
    	idcs = NULL;
    	len = len_a;
    	idcs = new int[len];
    }
    

Anmelden zum Antworten