Destruktor - samoczynne odpalanie

0

Mam pewien problem.
Nie wiem dlaczego destruktor macierzy sam się odpala ?

Klasa macierz:

#include "stdafx.h"
#include <iostream>
#include "macierz.h"
#include <cstdlib>

Macierz::Macierz(int Wiersz, int Kolumna)
{
	this->Wiersz = Wiersz;
	this->Kolumna = Kolumna;

	tablica = new int *[Wiersz];

	for (int i = 0; i < Wiersz; i++)
	{
		tablica[i] = new int[Kolumna];
	}
}

Macierz::Macierz(int Wiersz, int Kolumna, Macierz *macierz)
{
	Macierz(Wiersz, Kolumna);

	if ((macierz->Wiersz == Wiersz) && (macierz->Kolumna == Kolumna))
	{
		for (int i = 0; i < Wiersz; i++)
			for (int j = 0; j < Kolumna; j++)
				tablica[i][j] = macierz->tablica[i][j];
	}
	else
	{
		std::cout << "Nie mozna zainicjalizowac macierzy macierzą o innych rozmiarach" << std::endl;
	}
}

Macierz::Macierz(const Macierz & macierz)
{
	Wiersz = macierz.Wiersz;
	Kolumna = macierz.Kolumna;
	tablica = macierz.tablica;
}

int Macierz::get_value(int x, int y)
{
	int temp;

	if ((Wiersz > x) && (Kolumna > y))
	{
		temp = tablica[x][y];
	}
	else
	{
		std::cout << "Nie ma elementu o tym indeksie w tej macierzy" << std::endl;
		return 0;
	}
	return temp;
}

void Macierz::set_value(int x, int y, int value)
{
	if ((Wiersz > x) && (Kolumna > y))
	{
		tablica[x][y] = value;
	}
	else
	{
		std::cout << "Nie ma elementu o tym indeksie - nie mozna tam zapisac wartosci." << std::endl;
	}
}


int Macierz::wyznacznik()
{
	return det(*this);
}

int Macierz::det(Macierz x)
{
	int value = 0;

	if (x.Wiersz != x.Kolumna)
	{
		std::cout << "Nie mozna obliczyc wyznacznika macierzy niekwadratowej!" << std::endl;
		return 0;
	}

	// poniższy kod bedzie procedowany tylko wtedy jak mamy do czynienia z macierza kwadratowa

	if ((x.Wiersz == 1) && (x.Kolumna == 1))
	{
		return x.tablica[0][0];
	}
	else
	{
		for (int k = 0; k < x.Kolumna; k++)
		{
			Macierz *temp = new Macierz(x.Wiersz - 1, x.Kolumna - 1);

			for (int i = 1; i < x.Wiersz; i++)
			{
				for (int j = 0; j < x.Kolumna; j++)
				{
					if (j < k)
					{
						temp->set_value(i - 1, j, x.tablica[i][j]);
					}
					if (j > k)
					{
						temp->set_value(i - 1, j - 1, x.tablica[i][j]);
					}
				}
			}

			if ((k % 2) == 0)
			{
				value += x.tablica[0][k] * det(*temp);
			}
			else
			{
				value -= x.tablica[0][k] * det(*temp);
			}
		}
		return value;
	}
}

Macierz::~Macierz()
{
	for (int i = 0; i < Wiersz; i++)
	{
		delete (tablica[i]);
	}
	delete (tablica);
}

Funkcja główna programu

// MacierzLab.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <iostream>
#include <cstdlib>
#include "macierz.h"
#include "wektor.h"

using namespace std;

int main()
{
	// tworzymy macierz o wymiarach 0..2 i 0..3 (czyli macierz 3x4 elementową)
	Macierz * x = new Macierz(3, 3);
	x->set_value(0, 0, 1);
	x->set_value(0, 1, 2);
	x->set_value(0, 2, 3);

	x->set_value(1, 0, 2);
	x->set_value(1, 1, 3);
	x->set_value(1, 2, 4);

	x->set_value(2, 0, 1);
	x->set_value(2, 1, 0);
	x->set_value(2, 2, 1);


	cout << "Wyznacznik macierzy x wynosi : " << x->wyznacznik() << endl;

	system("PAUSE");
	return 0;
}

Cały kod generuje poprawne wyniki w sensie obliczenia wyznacznika macierzy jednakże nie wiem dlaczego ale nie mam żadnej możliwości kontroli wywołania destruktora.
Przez debugowanie ustaliłem że odpala mi się on samoczynnie i to w chwilach gdy odpalić się powinien... ;) jednak proszę mi wyjaśnić dlaczego się tak dzieje jeśli przecież nie używam do tego celu składni :

delete(temp);
3
Adamos19 napisał(a):

Mam pewien problem.
Nie wiem dlaczego destruktor macierzy sam się odpala ?

Klasa macierz:

#include "stdafx.h"
#include <iostream>
#include "macierz.h"
#include <cstdlib>
Macierz::Macierz(int Wiersz, int Kolumna, Macierz *macierz)
{
	Macierz(Wiersz, Kolumna);

Wygląda na stworzenie obiektu Macierz na stosie. Powinieneś wywołać ten konstruktor z listy inicjalizacyjnej.

4

Zacznijmy od podstaw, Twój desktruktor jest źle napisany, w ten sposób powinieneś zwalniać ręcznie zaolokowaną drwuwymiarową tablicę:

Macierz::~Macierz()
{
    for (int i = 0; i < Wiersz; i++)
    {
        delete[] tablica[i];
    }
    delete[] tablica;
}

A co do pytania:

Nie wiem dlaczego destruktor macierzy sam się odpala ?

Bo masz w jendym miejscu inicjalizacje na stosie:

Macierz::Macierz(int Wiersz, int Kolumna, Macierz *macierz)
{
    Macierz(Wiersz, Kolumna);

(edit) @nalik byłeś trochę szybszy ;)

0

Twierdzisz że instrukcja która w swojej składni ma "new" tworzy obiekt na stosie? Zgodnie z moją najlepszą wiedzą tak nie jest bo tworzy go na stercie zarządzalnej.
Zauważ ponadto że w kodzie w klasie macierz mamy w metodzie det coś takiego:

Macierz *temp = new Macierz(x.Wiersz - 1, x.Kolumna - 1);

Ja nie twierdzę że nie masz racji, wszystko wskazuje właśnie na to że MASZ ale JAKIM CUDEM????

0
several napisał(a):

Zacznijmy od podstaw, Twój desktruktor jest źle napisany, w ten sposób powinieneś zwalniać ręcznie zaolokowaną drwuwymiarową tablicę:

Macierz::~Macierz()
{
    for (int i = 0; i < Wiersz; i++)
    {
        delete[] tablica[i];
    }
    delete[] tablica;
}

A co do pytania:

Nie wiem dlaczego destruktor macierzy sam się odpala ?

Bo masz w jendym miejscu inicjalizacje na stosie:

Macierz::Macierz(int Wiersz, int Kolumna, Macierz *macierz)
{
    Macierz(Wiersz, Kolumna);

Przepraszam, rzeczywiście. Pomyłka. Poprawiłem to ale to nie ma wpływu na "samoczynne" odpalanie się destruktora.

3
Adamos19 napisał(a):

Twierdzisz że instrukcja która w swojej składni ma "new" tworzy obiekt na stosie?

Nikt tak nie napisał, także nie wiem skąd to sobie wziąłeś. W miejscu które wskazał @nalik i ja masz stworzoną tymczasową zmienną na stosie. Jeśli chcesz zawołać konstruktor z innego konstruktora to TUTAJ masz przykład jak to zrobić.

0
Adamos19 napisał(a):

Twierdzisz że instrukcja która w swojej składni ma "new" tworzy obiekt na stosie? Zgodnie z moją najlepszą wiedzą tak nie jest bo tworzy go na stercie zarządzalnej.

Oj, Oj, podstawy :) new wywoła konstruktor klasy Macierz. Wywołanie tego konstruktora stworzy na stosie wywołań funkcji nowy rekord aktywacji (ramkę stosu). Konstruktor jest źle napisany i tworzy obiekt tej samej klasy na stosie, w ramce wywołanej funkcji. Podczas wychodzenia z konstruktora (wywołanego przez new), obiekty stworzone na stosie zostaną zniszczone.

0

Przepraszam, rzeczywiście. Pomyłka. Poprawiłem to ale to nie ma wpływu na "samoczynne" odpalanie się destruktora.

Nic się samoczynnie nie odpala :D @nalik w pierwszej odpowiedzi napisał Ci co musisz zrobić, żeby zrobić poprawną delegację do innego konstruktora. Ja podałem Ci źródło, które trochę rozszerza temat. Nie wiem co możemy dla Ciebie więcej zrobić.

0

Ale konstruktor o którym Panowie piszecie nie może się odpalić bo nigdzie w kodzie nie wywołuję go (z trzema argumentami) a jedynie wywołuję konstruktor z dwoma argumentami który nie odpala już konstruktora żadnego wewnątrz siebie.
Innymi słowy, Panowie skróćmy ten kod o to o czym nie dyskutujemy, teraz wygląda to tak, a pytanie pozostaje ciągle AKTUALNE:

#include "stdafx.h"
#include <iostream>
#include "macierz.h"
#include <cstdlib>

Macierz::Macierz(int Wiersz, int Kolumna)
{
	this->Wiersz = Wiersz;
	this->Kolumna = Kolumna;

	tablica = new int *[Wiersz];

	for (int i = 0; i < Wiersz; i++)
	{
		tablica[i] = new int[Kolumna];
	}
}

int Macierz::get_value(int x, int y)
{
	int temp;

	if ((Wiersz > x) && (Kolumna > y))
	{
		temp = tablica[x][y];
	}
	else
	{
		std::cout << "Nie ma elementu o tym indeksie w tej macierzy" << std::endl;
		return 0;
	}
	return temp;
}

void Macierz::set_value(int x, int y, int value)
{
	if ((Wiersz > x) && (Kolumna > y))
	{
		tablica[x][y] = value;
	}
	else
	{
		std::cout << "Nie ma elementu o tym indeksie - nie mozna tam zapisac wartosci." << std::endl;
	}
}


int Macierz::wyznacznik()
{
	return det(*this);
}

int Macierz::det(Macierz x)
{
	int value = 0;

	if (x.Wiersz != x.Kolumna)
	{
		std::cout << "Nie mozna obliczyc wyznacznika macierzy niekwadratowej!" << std::endl;
		return 0;
	}

	// poniższy kod bedzie procedowany tylko wtedy jak mamy do czynienia z macierza kwadratowa

	if ((x.Wiersz == 1) && (x.Kolumna == 1))
	{
		return x.tablica[0][0];
	}
	else
	{
		for (int k = 0; k < x.Kolumna; k++)
		{
			Macierz *temp = new Macierz(x.Wiersz - 1, x.Kolumna - 1);

			for (int i = 1; i < x.Wiersz; i++)
			{
				for (int j = 0; j < x.Kolumna; j++)
				{
					if (j < k)
					{
						temp->set_value(i - 1, j, x.tablica[i][j]);
					}
					if (j > k)
					{
						temp->set_value(i - 1, j - 1, x.tablica[i][j]);
					}
				}
			}

			if ((k % 2) == 0)
			{
				value += x.tablica[0][k] * det(*temp);
			}
			else
			{
				value -= x.tablica[0][k] * det(*temp);
			}
			int p = 0;
			delete temp;
		}
		return value;
	}
}

Macierz::~Macierz()
{
	for (int i = 0; i < Wiersz; i++)
	{
		delete[] tablica[i];
	}
	delete[] tablica;
}


Natomiast za informacje o teorii dot. odpalania konstruktora z innego konstruktora serdecznie dziękuję, przydadzą się jeszcze w tym projekcie. ALE NIE TUTAJ!

2

A tutaj masz kolejny błąd:

int Macierz::wyznacznik()
{
    return det(*this);
}

int Macierz::det(Macierz x)
{

Jak już przekazywać to referencję albo wskaźnik. Klasa problemu ta sama. x zostanie zniszczone podczas wychodzenia z metody det. Niestety nie masz poprawnego konstruktora kopiującego, więc x przepisało sobie wskaźniki z this i w efekcie skasowało oryginalne dane.

0

Jesteś pewien, że odpala się znikąd?

Macierz *temp = new Macierz(x.Wiersz - 1, x.Kolumna - 1);
// ... 
int p = 0;
delete temp;

Dodałeś delete temp więc desktruktor powinieneś się odpalać.

0

No dobrze ale przecież w metodzie "det" mam tworzone słówkiem "new" kolejny obiekt który również jest niszczony ale nie bardzo wiem dlaczego.
Znaczy że co, że jeśli w ramach dowolnej funkcji wywołam komendę tworzącą obiekt opatrzoną słówkiem "new" to po zakończeniu tej funkcji obiekt ten istnieć nie będzie??? Bezsensu.

0

Tak, bo dodałem to dopiero potem. Miało tego nie być , ma być tak:

#include "stdafx.h"
#include <iostream>
#include "macierz.h"
#include <cstdlib>

Macierz::Macierz(int Wiersz, int Kolumna)
{
	this->Wiersz = Wiersz;
	this->Kolumna = Kolumna;

	tablica = new int *[Wiersz];

	for (int i = 0; i < Wiersz; i++)
	{
		tablica[i] = new int[Kolumna];
	}
}

int Macierz::get_value(int x, int y)
{
	int temp;

	if ((Wiersz > x) && (Kolumna > y))
	{
		temp = tablica[x][y];
	}
	else
	{
		std::cout << "Nie ma elementu o tym indeksie w tej macierzy" << std::endl;
		return 0;
	}
	return temp;
}

void Macierz::set_value(int x, int y, int value)
{
	if ((Wiersz > x) && (Kolumna > y))
	{
		tablica[x][y] = value;
	}
	else
	{
		std::cout << "Nie ma elementu o tym indeksie - nie mozna tam zapisac wartosci." << std::endl;
	}
}


int Macierz::wyznacznik()
{
	return det(*this);
}

int Macierz::det(Macierz x)
{
	int value = 0;

	if (x.Wiersz != x.Kolumna)
	{
		std::cout << "Nie mozna obliczyc wyznacznika macierzy niekwadratowej!" << std::endl;
		return 0;
	}

	// poniższy kod bedzie procedowany tylko wtedy jak mamy do czynienia z macierza kwadratowa

	if ((x.Wiersz == 1) && (x.Kolumna == 1))
	{
		return x.tablica[0][0];
	}
	else
	{
		for (int k = 0; k < x.Kolumna; k++)
		{
			Macierz *temp = new Macierz(x.Wiersz - 1, x.Kolumna - 1);

			for (int i = 1; i < x.Wiersz; i++)
			{
				for (int j = 0; j < x.Kolumna; j++)
				{
					if (j < k)
					{
						temp->set_value(i - 1, j, x.tablica[i][j]);
					}
					if (j > k)
					{
						temp->set_value(i - 1, j - 1, x.tablica[i][j]);
					}
				}
			}

			if ((k % 2) == 0)
			{
				value += x.tablica[0][k] * det(*temp);
			}
			else
			{
				value -= x.tablica[0][k] * det(*temp);
			}
		}
		return value;
	}
}

Macierz::~Macierz()
{
	for (int i = 0; i < Wiersz; i++)
	{
		delete[] tablica[i];
	}
	delete[] tablica;
}

a i tak się odpala!
Gdy dodam tą instrukcję "delete" to odpala się niejako ponownie na tym samym wskaźniku co już powoduje błąd w samym działaniu destruktora a to pewnie dlatego że odpalony raz modyfikuje sobie wskaźnik który mu pokazywał na obszar który miał zwolnić. A jak odpala się na zmodyfikowanym już wskaźniku to chce pisać po pamięci na co mu nie pozwala system wyrzucając właśnie taki wyjątek.
Pytanie pozostaje ciągle aktualne Panowie, z jakiej paki odpala mi się destruktor obiektu macierz jeśli go jawnie nie wywołuję instrukcją "delete" ???

0

a i tak się odpala!

Odpala się, z powodu kopiowania do argumentu w metodzie det, tak jak Ci @nalik napisał wcześniej.

1

Jeżeli mogę coś zasugerować, to wywal Pan w piz** to new i użyj std::vector.

tablica = vector<vector<int>>(wiersze, vector<int>(kolumny, 0));

Problem z niepoprawnym konstruktorem kopiującym zniknie. Co najwyżej będzie kopiował dane w tą i z powrotem, gdy nie użyjesz referencji.

0

Ok, jestem w stanie to przyjąć do wiadomości, dzięki!
Ale to dlaczego w takim razie powstaje błąd jeśli w tej metodzie chcę zwolnić to co przed momentem stworzyłem instrukcją:

Macierz *temp = new Macierz(x.Wiersz - 1, x.Kolumna - 1);

pisząc tą metodę tak:

int Macierz::det(Macierz x)
{
	int value = 0;

	if (x.Wiersz != x.Kolumna)
	{
		std::cout << "Nie mozna obliczyc wyznacznika macierzy niekwadratowej!" << std::endl;
		return 0;
	}

	// poniższy kod bedzie procedowany tylko wtedy jak mamy do czynienia z macierza kwadratowa

	if ((x.Wiersz == 1) && (x.Kolumna == 1))
	{
		return x.tablica[0][0];
	}
	else
	{
		for (int k = 0; k < x.Kolumna; k++)
		{
			Macierz *temp = new Macierz(x.Wiersz - 1, x.Kolumna - 1);

			for (int i = 1; i < x.Wiersz; i++)
			{
				for (int j = 0; j < x.Kolumna; j++)
				{
					if (j < k)
					{
						temp->set_value(i - 1, j, x.tablica[i][j]);
					}
					if (j > k)
					{
						temp->set_value(i - 1, j - 1, x.tablica[i][j]);
					}
				}
			}

			if ((k % 2) == 0)
			{
				value += x.tablica[0][k] * det(*temp);
			}
			else
			{
				value -= x.tablica[0][k] * det(*temp);
			}

                       delete temp;

		}
		return value;
	}
0
Adamos19 napisał(a):

Ok, jestem w stanie to przyjąć do wiadomości, dzięki!
Ale to dlaczego w takim razie powstaje błąd jeśli w tej metodzie chcę zwolnić to co przed momentem stworzyłem instrukcją:

Bo już zwolniłeś te dane wywołując det(*tmp). Wskaźniki są już niepoprawne. Prawdopodobnie tam gdzie wskazują nadal są stare dane, jeszcze nie nadpisane, więc odczyt się uda, ale kolejne wywołanie zwalniania pamięci nie.

0

Niemożliwe moim zdaniem ponieważ metodę det wywołuję właśnie tak:

det(*temp)

a zatem przekazuję jej obiekt i ona robi se z niego kopię, czyż nie?

1
Adamos19 napisał(a):

Niemożliwe moim zdaniem ponieważ metodę det wywołuję właśnie tak:

det(*temp)

a zatem przekazuję jej obiekt i ona robi se z niego kopię, czyż nie?

Tak. Ale robi kopię wywołując Twój konstruktor kopiujący. Twój konstruktor kopiujący to tak zwana płytka kopia, gdyż nie skopiował buforów tablicy utworzonych na stercie (nie alokował ich od nowa). W efekcie oba obiekty wskazują na to samo i oba próbują zwolnić to samo.

0
Adamos19 napisał(a):

tworzy go na stercie zarządzalnej.

Nie na „stercie zarządzalnej” tylko na po prostu stercie.

0

Dobra, już rozumiem!!! :)))
@Azarien a czym to się różni dokładnie?
@nalik bardzo dziękuję za wyjaśnienia, pomogłeś mi, do tej pory nie myślałem w ogóle nad tym w jaki sposób obiekt trafia poprzez argument do funkcji, kurcze a tu proszę.
W przypadku przekazywania przez wartość ODPALA się konstruktor kopiujący który robi "płytką" kopię obiektu (bez alokowania i przepisywania wartości elementów macierzy) a kopię tą tworzy na stosie, a zatem w przypadku zakończenia działania funkcji stos się zwija o ten zapis co powoduje obiekt zostaje niszczony a destruktor zajmuje się usunięciem tego obszaru. Zatem nie muszę już wywoływać delete i żadnych wycieków pamięci nie będzie! Czy tak ? D

1
Adamos19 napisał(a):

@nalik bardzo dziękuję za wyjaśnienia, pomogłeś mi, do tej pory nie myślałem w ogóle nad tym w jaki sposób obiekt trafia poprzez argument do funkcji, kurcze a tu proszę.
W przypadku przekazywania przez wartość ODPALA się konstruktor kopiujący który robi "płytką" kopię obiektu (bez alokowania i przepisywania wartości elementów macierzy) a kopię tą tworzy na stosie, a zatem w przypadku zakończenia działania funkcji stos się zwija o ten zapis co powoduje obiekt zostaje niszczony a destruktor zajmuje się usunięciem tego obszaru. Zatem nie muszę już wywoływać delete i żadnych wycieków pamięci nie będzie! Czy tak ? D

Tak, wszystko poza przedostatnim zdaniem. To jest niepoprawny kod i metodą poprawienia go nie jest dodanie kolejnego niepoprawnego kodu, który sprawi, że przypadkiem będzie działać, dopóki znowu nie wywołasz det albo innej niepoprawnej metody. Zmień parametry do metod, by przyjmowały referencję const Macierz& i zdecydowanie użyj std::vector lub (nie polecam, std::vector, już to robi) zaimplementuj konstruktor kopiujący i operator przypisania, które wykonają głęboką kopię buforów.

0

Jak napisać tą metodę:

int Macierz::wyznacznik()
{
	return det(*this);
}

aby współdziałała poprawnie z tą:

int Macierz::det(const Macierz & x)
{
	int value = 0;

	if (x.Wiersz != x.Kolumna)
	{
		std::cout << "Nie mozna obliczyc wyznacznika macierzy niekwadratowej!" << std::endl;
		return 0;
	}

	// poniższy kod bedzie procedowany tylko wtedy jak mamy do czynienia z macierza kwadratowa

	if ((x.Wiersz == 1) && (x.Kolumna == 1))
	{
		return x.tablica[0][0];
	}
	else
	{
		for (int k = 0; k < x.Kolumna; k++)
		{
			Macierz *temp = new Macierz(x.Wiersz - 1, x.Kolumna - 1);

			for (int i = 1; i < x.Wiersz; i++)
			{
				for (int j = 0; j < x.Kolumna; j++)
				{
					if (j < k)
					{
						temp->set_value(i - 1, j, x.tablica[i][j]);
					}
					if (j > k)
					{
						temp->set_value(i - 1, j - 1, x.tablica[i][j]);
					}
				}
			}

			if ((k % 2) == 0)
			{
				value += x.tablica[0][k] * det(*temp);
			}
			else
			{
				value -= x.tablica[0][k] * det(*temp);
			}
			delete temp;
		}
		return value;
	}
}

Przecież jeśli argumentem metody jest referencja to można ją przekazać za pomocą wskaźnika , czyż nie?

Jeśli nie, to jakiej składni powinienem użyć żeby przekazać referencje do obiektu "bieżącego", bo próbowałem tak: &this ale to generuje błąd ???

I ostatnie jeszcze tylko pytanie na koniec:
Nie rozumiem sensu zastosowania w tym wypadku predefiniowanej klasy vector ponieważ ja wykonując liczenie wyznacznika w żaden sposób nie mogę i nie chcę modyfikować bieżącego obiektu macierzy a to z kolei pociąga za sobą fakt że nie chcę nic "realokować" (ani obcinać macierzy źródłowej ani jej rozszerzać), a robić to muszę ponieważ tak wygląda to zgodnie ze wzorem na rozwinięcie metodą Laplace'a wyznacznika względem danego wiersza... jaką to niby przewagę będzie miało zastosowanie "vector" zamiast tego co ja zrobiłem i jak to użyć w moim kodzie? Chętnie się dowiem jeśli koledzy z łaski swojej napiszą.....

1

A co tym razem nie działa?

  1. Po pierwsze, nie musisz tworzyć macierzy temp przez new. Dlaczego? Bufory, których używa i tak istnieją na stosie, a przekazujesz ją do innych metod przez referencję, a wychodząc z metody, gdzie została utworzona i tak chcesz się jej pozbyć. Ergo, nie potrzebujesz tworzyć jej na stercie, może istnieć na stosie, w zakresie tej funkcji.
  2. &this to wskaźnik na wskaźnik
  3. Poprawne wywołanie to det(*this), gdyż chcesz mieć referencję do obiektu wskazywanego przez this.
Adamos19 napisał(a):

I ostatnie jeszcze tylko pytanie na koniec:
Nie rozumiem sensu zastosowania w tym wypadku predefiniowanej klasy vector ponieważ ja wykonując liczenie wyznacznika w żaden sposób nie mogę i nie chcę modyfikować bieżącego obiektu macierzy a to z kolei pociąga za sobą fakt że nie chcę nic "realokować" (ani obcinać macierzy źródłowej ani jej rozszerzać), a robić to muszę ponieważ tak wygląda to zgodnie ze wzorem na rozwinięcie metodą Laplace'a wyznacznika względem danego wiersza... jaką to niby przewagę będzie miało zastosowanie "vector" zamiast tego co ja zrobiłem i jak to użyć w moim kodzie? Chętnie się dowiem jeśli koledzy z łaski swojej napiszą.....

To jest bardziej pytanie o samo projektowanie. std::vector zapewnia Ci poprawną zarządzanie buforem - inizjalizacje, sprzątanie i kopiowanie. Jak sam widzisz pisanie tego z ręki to strata czasu i łatwo popełnić błąd. To samo co robisz przy użyciu własnych buforów możesz uzyskać z wykorzystaniem std::vector (przykładowo, referencja na vector nie skopiuje Ci buforów).
Jeżeli nie chcesz realokować danych, to masz takie opcje:
a) Twórz widok na obecną macierz, który powinien być osobną klasę. Widok nie będzie sprzątał, jedynie udawał macierz o mniejszym rozmiarze. Zamiast własnego buforu będzie trzymał odnośnik od prawdziwego buforu (np. przez referencję na std::vector). Oczywiście czas życia widoku nie może być większy niż oryginalnej macierzy, chyba, że zastosujesz zliczanie referencji do posprzątania.
b) Zmodyfikuj metody, by działały na oryginalnej macierzy, ale przyjmowały jako parametry zakres.
c) Używaj macierzy, które współdzielą bufory, ale taką płytką kopię twórz przy użyciu dedykowanej metody, a same bufory zapakuj w wskaźnik, który będzie zliczał referencję. Zakres będzie parametrem macierzy, nie buforu, który wykorzystujesz. I nie ma tutaj znaczenia, czy skorzystasz z vector czy z własnych buforów, logika będzie taka sama.

0

No dobra dobra, zgadzam się z Tobą ale przecież ja słówkiem new tworzę całkiem inną macierz, nie taką jak obecnie utworzona na stosie (rozmiarowo np. o jeden niżej niż bieżąca)....
Chyba jeszcze czegoś nie rozumiem... możesz powiedzieć która macierz została utworzona na stosie w chwili wywołania metody z przekazaną do niej przez referencję macierzą ?
Innymi słowy: co tworzy się na stosie i czy coś się tworzy jeśli metodę wywołuję i przekazuję do niej obiekt przez referencję...?

0
Adamos19 napisał(a):

No dobra dobra, zgadzam się z Tobą ale przecież ja słówkiem new tworzę całkiem inną macierz, nie taką jak obecnie utworzona na stosie (rozmiarowo np. o jeden niżej niż bieżąca)....

Tak, a zaraz potem ją kasujesz. Może lepiej utworzyć ją na stosie (przypominam, bufory i tak są na stercie), przekazywać przez referencję i pozwolić kompilatorowi posprzątać automatycznie?
I tak swoją drogą, w tym przypadku alokacja pamięci i tak się odbywa, więc równie dobrze mógł ją załatwić std::vector.

Chyba jeszcze czegoś nie rozumiem... możesz powiedzieć która macierz została utworzona na stosie w chwili wywołania metody z przekazaną do niej przez referencję macierzą ?

Jak przekazujesz *temp do det i nie używasz referencji, to tworzysz nową macierz tymczasową, która współdzieli bufor z temp.

Innymi słowy: co tworzy się na stosie i czy coś się tworzy jeśli metodę wywołuję i przekazuję do niej obiekt przez referencję...?

Zakładając przekazywanie przez referencję, to nic się nie utworzy od nowa.

Pomijam już fakt, że tworzenie nowych macierzy o takich samych rozmiarach (i to w dodatku przez new) jest wywoływane w pętli. Efektywniej byłoby stworzyć macierz raz i tylko ją czyścić, by przygotować do ponownego użycia.

0

Wszystko to co napisałeś w ostatnim poście jest dla mnie zrozumiałe poza jedną rzeczą:
Nie rozumiem pierwszego zdania:

"(...) Tak, a zaraz potem ją kasujesz. Może lepiej utworzyć ją na stosie (przypominam, bufory i tak są na stercie), przekazywać przez referencję i pozwolić kompilatorowi posprzątać automatycznie?
I tak swoją drogą, w tym przypadku alokacja pamięci i tak się odbywa, więc równie dobrze mógł ją załatwić std::vector."

Jak by to miało wyglądać, możesz mi wysłać te kilka linijek kodu do analizy ale najprościej jak to możliwe...
chciałbym zobaczyć bardzo o czym piszesz...

0

Panowie, cieniak ze mnie i nie potrafię zrozumieć działania <vectora>.
Mam kod:

	std::vector<Punkt3D *> v;

	while (1)
	{
		v.push_back(new Punkt3D(1, 2, 3));
		v.pop_back();
	}

lub inaczej:

	std::vector<Punkt3D *> v;

	while (1)
	{
		v.push_back(new Punkt3D(1, 2, 3));
		v.clear();
	}

Pytanie dlaczego on powoduje wyciek pamięci jeśli przecież pisaliście że vector powinien działać tak że daje sobie świetnie radę z zarządzaniem pamięcią...
Jeśli dokładam nowo tworzony obiekt do vector a potem ściągam ten obiekt z niego to dlaczego on się nie kasuje???

0

Bo wektor radzi sobie z tym, czym zarządza. W tym przypadku jest to wskaźnik na Punkt3D, a nie obiekt Punkt3D. Możesz uznać, że wywoływany destruktor wskaźnika nie różni się od destruktora inta - czyli nic nie robi.

1 użytkowników online, w tym zalogowanych: 0, gości: 1