funkcja zwraca wskaznik do dynamiocznej tablicy, operator delete[]

0

Witam. mam pytanie które nie daje mi spokoju.

Problem:

  • Funkcja wczytuje dane z pliku (zawartość elementów tablicy).
  • Podliczamy ilość elementów i tworzymy dynamiczną tablicę
  • Funkcja musi zwracać zawartość tablicy, a że nie może to musi zwrócić wskaźnik.

Pytanie:
Kiedy wobec tego powinienem użyć operatora delete [] ?

Uproszczona forma zadania

int* funkcja()
{
    int rozmiar;
    cin >> rozmiar;
    int *wsk = new int[rozmiar];

    // jakas operacja wypelniajaca tablice
    
    return wsk;
} 
1

Jak przestaniesz używać tych danych. Zamiast się tym martwić, użyj lepiej std::vector/std::unique_ptr/std::shared_ptr do przetrzymywania danych/wskaźnika. W nowoczesnym C++ używanie nagich wskaźników do czegokolwiek innego niż interakcji ze starymi bibliotekami oraz ewentualnie obserwacji (ale i to nie bardzo) to zbrodnia.

0

a jakiś inny sposób, niestety ale na uczelni, mają trochę staroświeckie zwyczaje :D

1

std::vector jest w standardzie od jego pierwszej wersji z 1998 roku (a i przed standaryzacją nie był nowością). Jeśli masz zakaz użycia jego, to pewnie też odpada boost::scoped_ptr/boost::shared_ptr z biblioteki Boost. W takim razie masz 2 opcje:

  1. Po prostu usuń dane za pomocą delete[] w miejscu, w którym przestajesz ich używać. Pamiętaj, że jak masz więcej instrukcji return lub cokolwiek w środku może rzucić wyjątek to musisz to wziąć pod uwagę
  2. Napisz własny scoped/shared pointer, to nie jest trudne dla podstawowego przypadku.

Ad.1
Np mając dwie ścieżki wyjścia z funkcji:

void foo()
{
	int* ptr = funkcja();
	
	if(ptr[0] == 42){
		delete[] ptr;
		bar();
		return;
	}
	
	qux(ptr);
	delete[] ptr;

	baz(ptr);

	return;
}

problem z nagimi wskaźnikami jest taki, że nie masz pojęcia czy qux() przejmuje kontrolę nad wskaźnikiem (t.j. czy zwalnia pamięć) oraz jeśli qux() rzuci wyjątek, to pamięć pod ptr nie zostanie zwolniona, więc finalnie ta funkcja powinna wyglądać tak:

void foo()
{
	int* ptr = funkcja();
	
	if(ptr[0] == 42){
		delete[] ptr;
		bar();
		return;
	}
	
	try{
		qux(ptr);
		delete[] ptr;
		baz();
	}catch(std::exception const& e){
		delete[] ptr;
		log(e.what());
	}
	
	return;
}
0

Raczej w stylu C (skoro całość jest w stylu C zrobiona), niech wywoła funkcje usuwającą, w której niech wywoła delete. Wywołanie jakiejkolwiek funkcji po której na sztywno wywołujemy delete to uczenie się złych nawyków.

2

Skoro masz taki durny wymóg, to wyjście jest jedno. Dobrze nazwać funkcję, tak by było wiadomo, że własność do pamięci jest przekazywana wywołującemu funkcję.

int* allocArrayFromStream(istream &inputs = cin) {
    
}

int *tab = allocArrayFromStream();
... // use data

delete[] tab;

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