Größe eines übergebenen Arrays bestimmen
-
@brotbernd
Sieht irgendwie doppelt gemoppelt ausObject::Object(float newX, float newY, float newZ, std::vector<CUSTOMVERTEX> &vertexArray) { std::for_each(vertexArray.begin(), vertexArray.end(), boost::bind(CopyCoordsToVec(_1, x, y, z))); } // Was auch immer du vor hast!?EDIT:
std::vector::size() returnt einen std::size_type mit der Größe des Vektors.
-
Schifty schrieb:
Ich brauche aber die Größe vom gesamten Array
Dann merk sie Dir irgendwo oder benutz etwas anderes als Zeiger!
-
Gerade diese Vertex Geschichte ist sehr wichtig für die Performance - ich würde ungern das Vertex-Array in vector überführen, nur um die Größe zu bestimmen und dann anschließend wieder mit dem Array arbeiten ... denn dieses brauche ich um über Memcopy einen VertexBuffer zu bauen.
EDIT:
Dort wo ich das Array erstelle, kann ich ja ohne Probleme auf die Gesamtgröße zugreifen - worin besteht denn der genaue Unterschied zwischen der Variable am Anfang und der im Funktionskopf - sind ja beides nur Pointer aufs erste Element, aber das eine liefert mir die Gesamtgröße, das andere nicht?
-
Du weißt hoffentlich das der Unterschied bei Bruchteilen von Millisekunden liegt?
-
Bei 10.000 Objekten mit ca. 200k CUSTOMVERTEX Punkten ist das schon deutlich spürbar. Insbesondere wenn ich 60 Frames die Sekunde rendern möchte....
-
wieso nimmst du überhaupt native arrays?
was spricht dagegen, direkt vector zu nehmen?
(bevor du dich mit angeblichen performance-problemen rausredest: es gibt keinen einzigen grund, wieso vector langsamer als nen c-array sein sollte...)wenn du native arrays brauchst, ist das mit vector auch kein problem:
std::vector<KOMISCHER_TYP> vec; //füllen oder resize oder was auch immer c_api_fkt(&vec[0], vec.size());bb
-
Wieso ich native Arrays verwenden möchte?
Weil ich keine Ahnung ob und wie memcpy mit vector funktioniert.
Vertices ist im folgenden mein CUSTOMVERTEX Array.
pVoidist mit einem meiner VertexBuffer verknüpftmemcpy(pVoid, currentObject->vertices, vertexCount*sizeof((*currentObject->vertices)));
Wenn der Befehl gehen würde, wäre vector eine sinnvolle Alternative.
-
Schifty schrieb:
Gerade diese Vertex Geschichte ist sehr wichtig für die Performance - ich würde ungern das Vertex-Array in vector überführen, nur um die Größe zu bestimmen und dann anschließend wieder mit dem Array arbeiten ... denn dieses brauche ich um über Memcopy einen VertexBuffer zu bauen.
Klingt so, als würdest Du nicht die Garantie kennen, die std::vector macht. Die Elemente stehen alle hintereinander im Speicher. Du kannst Dir also ein Zeiger-Paar so geben lassen und auch benutzen:
void foo(double const* beg, double const* end); void bar(std::vector<double> const& vec) { double const* beg = vec.empty() ? 0 : &vec.front(); double const* end = beg + vec.size(); foo(beg,end); }Schifty schrieb:
EDIT:
Dort wo ich das Array erstelle, kann ich ja ohne Probleme auf die Gesamtgröße zugreifen - worin besteht denn der genaue Unterschied zwischen der Variable am Anfang und der im Funktionskopf - sind ja beides nur Pointer aufs erste Element, aber das eine liefert mir die Gesamtgröße, das andere nicht?
Wie bitte? Formuliere das mal um, dass ich das auch verstehe, was Du meinst. Was meinst Du mit "Variable am Anfang" und "Variable im Funktionskopf"? Was für einen Unterschied soll es da geben?
Gruß,
SP
-
Jopp, memcpy geht - std::copy wäre aber eine sinnvolle alternative

dann entfällt dieses hässliche sizeof(...) auch und langsamer sollte es auch wieder nicht sein...bb
-
Tut mir Leid für die unsaubere Formulierung, war auf dem Sprung beim Edit.
Wenn ich das Array in der Main erstelle
CUSTOMVERTEX cube[] = {...};
und direkt dahinter sizeof(cube) schreibe
erhalte ich die Größe des gesamten Arrays.Übergebe ich an eine Funktion:
new Object(cube);Object::Object(CUSTOMVERTEX vertexArray[]) {...}
Und schreibe hier sizeof(vertexArray) erhalte ich die
größe des Pointers, bzw mit * die Größe des ersten Elements.Ich dachte es handelt sich in beiden Fällen um Pointer auf das erste Element?
Wo liegt der unterschied, und gibt es eine Möglichkeit im letzteren Fall, ersteres sizeof-Ergebnis zu erlangen?
-
Schifty schrieb:
gibt es eine Möglichkeit im letzteren Fall, ersteres sizeof-Ergebnis zu erlangen?
nein
-
Wenn du eine Funktion aufrufst (das gilt auch für die main) wird für sie ein Stackframe eingerichtet um für alle lokalen Variablen usw. Speicher einzurichten.
Und wenn du in einem solchen Stackframe nun lokal ein array erzeugst, sind die Größeninformationen halt noch vorhanden weil halt alle Elemente aufeinanderfolgend in diesem Tackframe liegen(Um missverständnissen vorzubeugen, die Informationen sind nicht vorhanden weil der Speicher aufeinander folgend reserviert ist, sondern weil dies im Stackframe geschieht). Wenn du dieses array nun einer Funktion übergibst wird für sie ebenfalls ein Stackframe eingerichtet, welche jedoch nur Speicher für diesen Zeiger reserviert, wodurch dieser nunmal nichts mehr über die größe des Arrays weiß.Aber in beiden Fällen handelt es sich wie du schon sagtest intern um einen Zeiger. Doch erkennt der Compiler natürlich wann du so ein Ding auch wirklich als array deklariert hast.
Aber wie gesagt, dass funktioniert nur weil die Informationen aus dem Stackframe ermittelt werden können so ein Array fürht keinerleich Verwaltungsinformationen mit sich, am Ende hast du mit so einem array halt "nur" aufeinander folgenden Speicher für Mehrere Objekte eines Typs und nicht mehr.--------------------------
Und wenn du wirklich ein eigenes Array anlegen möchtest ohne auf die Größeninformationen zu verzichten, könntest du dir im ersten Element oder je nachdem wie du das handhabst vor dem Ersten Element die Anzahl der Elemente als int speichern.
-
Schifty schrieb:
Wenn ich das Array in der Main erstelle
CUSTOMVERTEX cube[] = {...};
und direkt dahinter sizeof(cube) schreibe erhalte ich die Größe des gesamten Arrays.
Korrekt. Größe in Bytes.
Schifty schrieb:
Übergebe ich an eine Funktion:
new Object(cube);Object::Object(CUSTOMVERTEX vertexArray[]) {...}
Und schreibe hier sizeof(vertexArray) erhalte ich die
größe des Pointers, bzw mit * die Größe des ersten Elements.Korrekt.
Schifty schrieb:
Ich dachte es handelt sich in beiden Fällen um Pointer auf das erste Element? Wo liegt der unterschied,
Nein. Das erste ist ein Array vom Typ CUSTOMVERTEX[N] (nicht CUSTOMVERTEX[] !) mit N=Anzahl der Elemente. Das zweite ist ein Zeiger. Großer Unterschied!
C++ erlaubt Dir einfach bei der Definition von
cubedas N wegzulassen. Der Compiler ist so schlau, dass er das selbst einsetzen kann, nachdem er die Elemente gezählt hat.Der Typ CUSTOMVERTEX[] hingegen wird in der Parameterliste einer Funktion zu CUSTOMVERTEX übersetzt*. Auch eine Größe, falls angegeben, wird ignoriert. Diese Ersetzung des Typs findet statt, weil es in C auch so ist, weil man dachte es wäre praktisch, und weil Arrays keine Kopier-Semantik haben. Diese Ersetzung gibt es nur, falls das [] sich auf der "obersten Ebene" befindet. Ein Zeiger (
int(*)[3]) oder eine Referenz (int(&)[3]) auf ein Array gibt es also als möglichen Parameter.CUSTOMVERTEX[] ist aber auch als "unvollständiger Typ" in einer Deklaration auf globaler bzw Namensraum Ebene und innerhalb von Klassen für statische Elemente zulässig (Array mit Größe, die nicht verraten wird). Da es sich in dieser Situation um einen unvollständigen Typ handelt, ist die Anwendung von
sizeofgar nicht zulässig.Schifty schrieb:
und gibt es eine Möglichkeit im letzteren Fall, ersteres sizeof-Ergebnis zu erlangen?
Nur, wenn Du den Konstruktor von
Objectänderst. Hier mal eine Inspiration:template<typename T> class referenz_auf_bloedes_array { T* base_; std::size_t size_; public: referenz_auf_bloedes_array(T* base, std::size_t N) : base_(base), size_(N) {} template<std::size_t N> referenz_auf_bloedes_array(T (&ref)[N]) : base_(ref), size_(N) {} std::size_t size() const {size_;} T& operator[](std::ptrdiff_t idx) const {return base_[idx];} }; void foo(referenz_auf_bloedes_array<int> r) { if (3u <= r.size()) { r[0] = 1; r[1] = 2; r[2] = 3; } } int main() { int xx[] = {9,9,9,9,9}; foo(xx); }Gruß,
SP