Tu jest kilka zagadnień które trzeba dotknąć:
1. Tablica w języku C++ ("odziedziczona po C"), przy przesyłaniu do funkcji, wymaga przekazania wymiaru. Jeśli upierasz się na tablice, będzie konieczne zdefiniowanie tego wymiaru i konsekwentne stosowanie wszędzie gdzie występuje tablica. Innym rozwiązaniem będzie przesyłanie tego wymiaru za każdym razem do funkcji. Możliwe definicje funkcji:
void func1(float table1[20]);
void func2(float * table1, size_t table_length);
// Lub..
constexpr static size_t table_size = 5;
void func3(float table3[table_size]);
Wprawdzie jest możliwe dedukowanie wymiaru z szablonu ale to technika która ma konsekwencje.
2. Zwrócenie wartości w postaci tablicy z funkcji, będzie wymagało alokowania pamięci na stercie. Znów tablica "gubi wymiar" i w zasadzie jedyne co możesz zrobić to zwrócić wskaźnik. Trzeba wtedy użyć new i po sobie posprzątać poprzez delete. W przeciwnym wypadku dojdzie do wycieku pamięci. Obecnie jednak już nie ma powodu by posługiwać się "gołym new/delete" i stosuje się wskaźniki inteligentne.
Przykład z new/delete:
#include <iostream>
using namespace std;
constexpr static size_t table_size = 5;
float * Super_Grzybo_Suchar (float grzyb[table_size], float suchar[table_size])
{
float * wynik = new float[table_size]; // Alokowanie miejsca na stercie
for (size_t i = 0; i < table_size; ++i)
{
wynik[i] = grzyb[i] + suchar[i];
}
return wynik;
}
int main()
{
float Grzybki[]= {60.04, 0, 598.56, 24.04, 32.1};
float Sucharki[]= {57.58, 0, 582.12, 24.88, 31.1};
float * wynik = Super_Grzybo_Suchar(Grzybki, Sucharki);
cout << "Wynik to: ";
for(size_t i = 0; i < table_size; ++i) {
cout << wynik[i] << ' ';
}
cout << '\n';
delete [] wynik; // Tu sprzątanie.
}
Przykład z unique_ptr. Jak widać nie trzeba "sprzątać". Podawałem typy jawnie abyś wiedział co się dzieje. Jak widzisz dalej jest problem z rozmiarem. Inteligentny wskaźnik rozwiązuje problem usuwania z pamięci a nie rozmiaru tablicy.
#include <iostream>
#include <memory>
using namespace std;
constexpr static size_t table_size = 5;
unique_ptr<float[]> Super_Grzybo_Suchar (float grzyb[table_size], float suchar[table_size])
{
unique_ptr<float[]> wynik = make_unique<float[]>(table_size); // Alokowanie miejsca na stercie
for (size_t i = 0; i < table_size; ++i)
{
wynik[i] = grzyb[i] + suchar[i];
}
return wynik;
}
int main()
{
float Grzybki[]= {60.04, 0, 598.56, 24.04, 32.1};
float Sucharki[]= {57.58, 0, 582.12, 24.88, 31.1};
unique_ptr<float[]> wynik = Super_Grzybo_Suchar(Grzybki, Sucharki);
cout << "Wynik to: ";
for(size_t i = 0; i < table_size; ++i) {
cout << wynik[i] << ' ';
}
cout << '\n';
}
3. I na koniec dedukcja poprzez szablon, inteligentne wskaźniki, typ auto:
#include <iostream>
#include <memory>
using namespace std;
constexpr static size_t table_size = 5;
template<typename T, size_t N>
auto Super_Grzybo_Suchar (T (&grzyb)[N], T (&suchar)[N])
{
auto wynik = make_unique<T[]>(N); // Alokowanie miejsca na stercie
for (size_t i = 0; i < N; ++i)
{
wynik[i] = grzyb[i] + suchar[i];
}
return wynik;
}
int main()
{
float Grzybki[table_size] = {60.04, 0, 598.56, 24.04, 32.1};
float Sucharki[table_size] = {57.58, 0, 582.12, 24.88, 31.1};
auto wynik = Super_Grzybo_Suchar(Grzybki, Sucharki);
cout << "Wynik to: ";
for(size_t i = 0; i < table_size; ++i) {
cout << wynik[i] << ' ';
}
cout << '\n';
}
Wow... jaka fajna zabawka! Tyko...
4. Powiedz po co to wszystko robić kiedy masz .... vector? Sam zajmie się usunięciem z pamięci danych, przechowuje wielkość i nie zawracasz sobie głowy rzeczami które opisałem wcześniej:
#include <iostream>
#include <vector>
using namespace std;
auto Super_Grzybo_Suchar (const vector<float>& grzyb,
const vector<float>& suchar)
{
auto wynik = grzyb;
for (size_t i = 0; i < grzyb.size(); ++i)
{
wynik[i] += suchar[i];
}
return wynik;
}
int main()
{
vector<float> Grzybki = {60.04, 0, 598.56, 24.04, 32.1};
vector<float> Sucharki = {57.58, 0, 582.12, 24.88, 31.1};
auto wynik = Super_Grzybo_Suchar(Grzybki, Sucharki);
cout << "Wynik to: ";
for(const auto v: wynik) {
cout << v << ' ';
}
cout << '\n';
}