Rückgabe eines lokalen Vektors
-
Ich möchte den Code mit C-Arrays gerne durch Vector Arrays ersetzen:
double * SimulationData::getSpectrumArray(int & SizeX, int & SizeY) { SizeX = saveIteration; SizeY = ArrayDataPoints; double * Array = new double[SizeX * SizeY]; memcpy(Array, &SpectralAmplitudeArray[0], SizeX * SizeY * sizeof(double)); return Array; }Wenn ich aber ein lokales vector Array erstelle wird das gelöscht bevor die Referenz zurückgegeben wird:
vector<double> & SimulationData::getSpectrumArray(int & SizeX, int & SizeY) { SizeX = saveIteration; SizeY = ArrayDataPoints; vector<double> Array; std::copy(SpectralAmplitudeArray.begin(), SpectralAmplitudeArray.begin() + SizeX * SizeY, Array.begin()); return Array; }Wenn ich auf Pointer zurückgehen, habe ich den Vorteil des vectors nicht mehr, und würde dazu noch einen shared_ptr o. ä. basteln.
Welche Möglichkeiten hätte ich noch?
-
vector<double> SimulationData::getSpectrumArray(int & SizeX, int & SizeY) { SizeX = saveIteration; SizeY = ArrayDataPoints; vector<double> Array; std::copy(SpectralAmplitudeArray.begin(), SpectralAmplitudeArray.begin() + SizeX * SizeY, Array.begin()); return Array; }Gib einfach eine Kopie zurück und keine Referenz.
-
pospiech schrieb:
Welche Möglichkeiten hätte ich noch?
- Rückgabetyp
std::vector<double>und beten, dass (N)RVO richtig angewandt wird. - sicherer: einen
std::vector<double>&als Parameter. Leeren Container übergeben und füllen.
Übrigens brauchst du
std::copy()nicht, wenn du den Konstruktor von einer Iterator-Range einsetzt.
- Rückgabetyp
-
Nexus schrieb:
pospiech schrieb:
Welche Möglichkeiten hätte ich noch?
- Rückgabetyp
std::vector<double>und beten, dass (N)RVO richtig angewandt wird. - sicherer: einen
std::vector<double>&als Parameter. Leeren Container übergeben und füllen.
Bevor jemand den Code anfasst der RVO nicht kennt, und daran rumändert lasse ich es lieber ganz. Als Parameter war mir auch schon eingefallen, ist nur nicht ganz so schön.
Nexus schrieb:
Übrigens brauchst du
std::copy()nicht, wenn du den Konstruktor von einer Iterator-Range einsetzt.Mir ist nicht klar was du meinst und wie es stattdessen aussehen sollte.
- Rückgabetyp
-
pospiech schrieb:
Bevor jemand den Code anfasst der RVO nicht kennt, und daran rumändert lasse ich es lieber ganz.
Was heisst "lassen"? Irgendwie musst du das Problem ja lösen. Und der Programmierer muss RVO nicht kennen, nur der Compiler.
pospiech schrieb:
Als Parameter war mir auch schon eingefallen, ist nur nicht ganz so schön.
Wenn Performance hier nicht entscheidend ist, machs mit einer Kopie als Rückgabewert. Gut möglich, dass das rausoptimiert wird (eben NRVO/RVO). Falls du dieses Risiko allerdings nicht eingehen kannst, musst du vielleicht Effizienz vor Eleganz stellen.
pospiech schrieb:
Mir ist nicht klar was du meinst und wie es stattdessen aussehen sollte.
Hier siehst du die Konstruktoren von
std::vector. Der dritte hat folgende Deklaration:template <class InputIterator> vector (InputIterator first, InputIterator last, const Allocator& = Allocator());Also könntest du in deinem Beispiel gleich die Iterator-Range an den Konstruktor übergeben:
std::vector<double> Array( SpectralAmplitudeArray.begin(), SpectralAmplitudeArray.begin() + SizeX * SizeY);
-
Bevor jemand den Code anfasst der RVO nicht kennt, und daran rumändert lasse ich es lieber ganz. Als Parameter war mir auch schon eingefallen, ist nur nicht ganz so schön.
RVO ist, wie es der Name sagt eine Optimierung und hat (ausser in merkwürdigen Konstrukten) keine Nebenwirkungen auf den Sinn des Codes.
In anbetracht der Exceptionsicherheit ist der Parameter wohl am besten geeignet.