std::array C++11
-
Da ich die Größe meines Speichers zur Compilezeit kenne und diese sich auch zur Laufzeit niemals ändern wird wäre doch ein std::array sinnvoller als ein std::vector?
Allerdings scheint ein std::array auf dem Stack zu liegen und damit ist die Größe beschränkt. Also macht es doch wieder keinen Sinn folgendes zu bauen und damit schon ~1MB vom Stack zu klauen?
#include <array> std::array<FooClass, 1 << 16> ht; // sizeof(FooClass) = 64 Byte
Also trotz Array-Eigenschaften doch lieber einen Vector verwenden, oder?
#include <vector> std::vector<FooClass> ht(1 << 16); // sizeof(FooClass) = 64 Byte
-
du kannst auch einen std::unique_ptr als vector ohne overhead missbrauchen.
-
Was sagt da eigentlich der Standard zu std::array? In §23.3.2 steht nix darüber, dass der Speicher auf dem Stack liegen muss (oder übersehe ich da was?)
Wäre es dann nicht angebracht, dass array selbst entscheidet, wann ein Array auf dem Stack oder dem Heap liegen soll?!
-
Nun, ein std::array ist ein "aggregate type with the same semantics as a struct holding a C-style array". Nicht der Array entscheidet, wo er zu liegen kommt, sondern der Programmierer.
array<int, 3> a; // Stack auto *b = new array<int, 3>; // Heap.
Zu Tomahawk: Ja, std::array macht hier mehr Sinn. Du musst es ja nicht unbedingt auf den Stack hauen, sondern kannst es irgendwo platzieren.
FG
-
auto *b = new array<int, 3>; // Heap.
Und was ist das? Eigentlich nur ein
vector
. Aber mit Zeigern. Unschön.Nein, hier brauchst du einfach einen
vector
, dem du bei der Initialisierung die Größe mitgibst. Damit hast du auch nur eine Heap-Allokation, also praktisch genauso schnell wie beiarray
.Edit:
Wäre es dann nicht angebracht, dass array selbst entscheidet, wann ein Array auf dem Stack oder dem Heap liegen soll?!
Du denkst an
std::dynarray
.(oder übersehe ich da was?)
Schau mal in die Header-Vorgabe. Da steht genau, wie
std::array
zu definieren ist. Das einzige Member-Objekt ist ein Array:T elems[N]; // exposition only [von §23.3.2.1/3]
-
Es ging mir um das Prinzip. Der Programmierer bestimmt, wo der Speicher liegt, da std::array im Prinzip nur ein simples struct ohne Pointer ist. Du kannst den std::vector gerne auf den Stack werfen; seine Elemente liegen aber nicht dort, sondern in der Regel eben auf dem Heap.
Deklarierst du hingegen den std::array auf dem Stack, dann liegen auch die Elemente dort. Deklarierst du den Array global, dann liegen die Elemente im Data Segment (oder wo auch immer). Ein Array besteht aus seinen Elementen und sonst gar nichts. Ein Vector besteht aus irgend etwas, in der Regel aus zwei Zeigern, damit die Elemente irgendwo liegen können.
-
Arcoth schrieb:
Schau mal in die Header-Vorgabe. Da steht genau, wie
std::array
zu definieren ist. Das einzige Member-Objekt ist ein Array:T elems[N]; // exposition only [von §23.3.2.1/3]
Genau das ist der Knackpunkt. Die wörtliche Übersetzung für exposition ist sowas wie Ausstellung. Ich würde das sinngemäß so übersetzen wie "Nur ums zu zeigen wie es gehen könnte". Sprich: das Array könnte auch sonst wie implementiert sein.
Moment, mir fällt auch grad ein, der Standard kennt ja sowas wie Heap oder Stack gar nicht...
-
Nein, nein. Der Kommentar heißt hier einfach, dass der Name des Arrays nur als Beispiel gegeben ist, und kein tatsächlicher Member von
array
ist.
-
17.5.2.3 lesen und verstehen
-
camper schrieb:
17.5.2.3 lesen und verstehen
Es kann praktisch nur ein echtes Array als Member geben. Der Standard fordert eine Initialisierungssyntax (s. §23.3.2.1/2), die nur ein Array als Member ermöglicht. Ein
vector
fällt durch, weil brace-elision nur für Aggregate funktioniert.Die einzige andere Möglichkeit besteht darin, das Subaggregat so zu definieren, dass es genauso viele Member hat wie das Template-Argument vorgibt. Das ist nur leider impraktikabel, da so nur eine maximale Größe von 4096 möglich wäre - siehe Anhang B.
-
also mir fällt da so ein
template <typename T, size_t N> struct array { ... T elems[1][1][1][1][1][N][1][1][1][1]; };
oder
template <typename T, std::size_t N> struct array { array<T,(N+1)/2> x; array<T,N/2> y; }; template <typename T> struct array<T,1> { T x; }; template <typename T> struct array<T,0> { };
-
Eines Tages erwisch' ich dich, du mieser Hund!
-
Warte! Letzteres ist gar nicht Standardkonform, weil...
Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other
Und
The elements of an
array
are stored contiguously, meaning that ifa
is anarray<T, N>
then it obeys the identity&a[n] == &a[0] + n
for all0 <= n < N
.
-
Skym0sh0 schrieb:
Wäre es dann nicht angebracht, dass array selbst entscheidet, wann ein Array auf dem Stack oder dem Heap liegen soll?!
Das wäre fein, sagen wir mal ab 65k geht's auf den Heap.
Könnte gcc Compilererweiterungen einbasteln, und in der gcc-stdlib benutzen, damit das klappt und dem Standard nicht widerspricht?
-
Könnte gcc Compilererweiterungen einbasteln, und in der gcc-stdlib benutzen, damit das klappt und dem Standard nicht widerspricht?
Warum nicht einfach selber was basteln? Mit partieller Spezialisierung ist das ein Klacks. Muss doch nicht in den Standard,
dynarray
hats auch nicht geschafft.Und ich will mal sehen, wie man da um den Standard herum kommt, gerade wegen der Speicherkontinuitätsregel und der Initialisierungssyntax. Ich wette, jetzt gehen auch camper die Ideen aus.
-
Hier, so ähnlich:
#include <vector> #include <memory> template< typename T, std::size_t N, typename=void > struct Array { T _elems[N]; // evt. mit Trick um zero-size-arrays zu erlauben // ... }; template< typename T, std::size_t N > struct Array<T, N, typename std::enable_if<N >= (1 << 16)>::type> { std::unique_ptr<T[]> _elems{ new T[N] }; // .. }; int main() { Array<int, 70000> a; }
So ist es sogar immer noch ein Aggregat.
-
Arcoth schrieb:
Könnte gcc Compilererweiterungen einbasteln, und in der gcc-stdlib benutzen, damit das klappt und dem Standard nicht widerspricht?
Warum nicht einfach selber was basteln? Mit partieller Spezialisierung ist das ein Klacks. Muss doch nicht in den Standard,
dynarray
hats auch nicht geschafft.Jo, was lokales dazu habe ich schon seit 10 Jahren, naja so ähnlich, den Vector<type,size,onHeap=(size>=8192)> oder so. Array brauche ich eher nie, weil irgendwie die Daten dann doch angekrochen oder gestreamt oder berechnet mit ungewisser Ergebnisanzahl oder so kommen.
Wenn ich man drüber nachdenke, würde wohl auch >=64 fast reichen, denn wenn man die 64 Elemente tatsächlich anfassen will, kostet gegen die Berechnungen im Vector/Array das Allokieren/Deallokieren gar nicht mehr als einen Takt pro Element. Pah, 64-Bitter packen 8192 kompromisslos. Hast mich wieder zu nutzlosem Nachdenken gebracht, Du Schalk.
-
Ich - bin - kein - Schalk! Du bist der Schalk!
-
Arcoth schrieb:
Ich - bin - kein - Schalk! Du bist der Schalk!
Wird noch, ich setze weiterhin große Hoffnungen in Dich.
-
Arcoth schrieb:
Warte! Letzteres ist gar nicht Standardkonform, weil...
Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other
genau: might
Nirgendwo wird verlangt, dass die Implementation der Standardbibliothek portabel sein muss.Arcoth schrieb:
template< typename T, std::size_t N > struct Array<T, N, typename std::enable_if<N >= (1 << 16)>::type> { std::unique_ptr<T[]> _elems{ new T[N] }; // .. };
So ist es sogar immer noch ein Aggregat.
Ich glaube nicht. Initialisierer für nicht-statischen Member und so...