Ψάχνει για C ++ STL-σαν τάξη φορέα αλλά χρησιμοποιώντας αποθήκευσης στοίβα

ψήφοι
44

Πριν γράψω τη δική μου, θα ζητήσω από όλους y'all.

Ψάχνω για μια κατηγορία C ++ που είναι σχεδόν ακριβώς όπως ένα φορέα STL, αλλά αποθηκεύει δεδομένα σε μια σειρά στη στοίβα. Κάποιο είδος της STL κατηγορίας κατανεμητή θα εργαστεί επίσης, αλλά εγώ προσπαθώ να αποφευχθεί κάθε είδους σωρό, ακόμα και στατική διατεθεί σωρούς ανά νήμα (αν και ένα από αυτά είναι η δεύτερη επιλογή μου). Η στοίβα είναι λίγο πιο αποτελεσματική.

Πρέπει να είναι σχεδόν μια σταγόνα στον αντικατάσταση για την τρέχουσα κώδικα που χρησιμοποιεί ένα φορέα.

Για ό, τι ήμουν έτοιμος να γράψω εγώ σκεφτόμουν κάτι σαν αυτό:

char buffer[4096];
stack_vector<match_item> matches(buffer, sizeof(buffer));

Ή η τάξη θα μπορούσε να έχει χώρο buffer που διατίθενται στο εσωτερικό. Τότε θα μοιάζει με:

stack_vector<match_item, 256> matches;

Σκεφτόμουν ότι θα ρίξει std :: bad_alloc αν εξαντληθεί ο χώρος, αν και αυτό δεν πρέπει να συμβεί ποτέ.

Εκσυγχρονίζω

Χρησιμοποιώντας stack_container.h του Chromium λειτουργεί μεγάλο!

Ο λόγος που δεν είχα σκεφτεί να κάνει αυτό τον τρόπο τον εαυτό μου είναι ότι έχω πάντα παραβλέπεται την παράμετρο αντικείμενο εκχώρησης με τους κατασκευαστές συλλογή STL. Έχω χρησιμοποιήσει την παράμετρο προτύπου μερικές φορές για να κάνει στατική πισίνες, αλλά ποτέ δεν είχα δει κώδικα ή γραπτή οποιοδήποτε που χρησιμοποιείται στην πραγματικότητα την παράμετρο αντικειμένου. Έμαθα κάτι νέο. Πολύ κουλ!

Ο κωδικός είναι λίγο βρώμικο και για κάποιο λόγο GCC με ανάγκασε να κηρύξει την κατανεμητή ως ένα πραγματικό στοιχείο, αντί της κατασκευής του σε παράμετρος εκχώρησης φορέα του ιού. Πήγε από κάτι σαν αυτό:

typedef std::pair< const char *, const char * > comp_list_item;
typedef std::vector< comp_list_item > comp_list_type;

comp_list_type match_list;
match_list.reserve(32);

Σε αυτό:

static const size_t comp_list_alloc_size = 128;
typedef std::pair< const char *, const char * > comp_list_item;
typedef StackAllocator< comp_list_item, comp_list_alloc_size > comp_list_alloc_type;
typedef std::vector< comp_list_item, comp_list_alloc_type > comp_list_type;

comp_list_alloc_type::Source match_list_buffer;
comp_list_alloc_type match_list_alloc( &match_list_buffer );
comp_list_type match_list( match_list_alloc );
match_list.reserve( comp_list_alloc_size );

Και οφείλω να επαναλάβω ότι κάθε φορά που δηλώνω ένα νέο. Αλλά λειτουργεί ακριβώς όπως το ήθελα.

Παρατήρησα ότι stack_container.h έχει StackVector ορίζεται και δοκίμασα τη χρήση του. Αλλά δεν κληρονομεί από τον φορέα ή να ορίσετε τις ίδιες μεθόδους έτσι δεν ήταν μια σταγόνα-σε αντικατάσταση. Δεν ήθελα να ξαναγράψει όλο τον κώδικα με τη χρήση του φορέα έτσι έδωσα επάνω σε αυτό.

Δημοσιεύθηκε 09/12/2008 στις 23:15
πηγή χρήστη
Σε άλλες γλώσσες...                            


10 απαντήσεις

ψήφοι
38

Δεν χρειάζεται να γράψετε μια εντελώς νέα κατηγορία εμπορευματοκιβωτίων. Μπορείτε να κολλήσετε με τα δοχεία STL σας, αλλά να αλλάξει η δεύτερη παράμετρος, για παράδειγμα std::vectorγια να του δώσει το προσαρμοσμένο εκχώρησης που διαθέτει από μια στοίβα-ρυθμιστικό. Οι συγγραφείς χρώμιο έγραψε ένα εκχώρησης ακριβώς γι 'αυτό:

https://chromium.googlesource.com/chromium/chromium/+/master/base/stack_container.h

Λειτουργεί με τη χορήγηση μιας buffer όπου μπορείτε να πω πόσο μεγάλο είναι. Μπορείτε να δημιουργήσετε το δοχείο και κλήση container.reserve(buffer_size);. Αν υπερχείλιση αυτό το μέγεθος, το εκχώρησης θα πάρει αυτόματα τα στοιχεία από το σωρό (δεδομένου ότι προέρχεται από std::allocator, θα σε αυτή την περίπτωση να χρησιμοποιήσετε μόνο τις εγκαταστάσεις του προτύπου εκχώρησης). Δεν το έχω δοκιμάσει, αλλά φαίνεται σαν να είναι από το google έτσι νομίζω ότι αξίζει μια δοκιμή.

Χρήση είναι κάπως έτσι:

StackVector<int, 128> s;
s->push_back(42); // overloaded operator->
s->push_back(43);

// to get the real std::vector. 
StackVector<int, 128>::ContainerType & v = s.container();
std::cout << v[0] << " " << v[1] << std::endl;
Απαντήθηκε 09/12/2008 στις 23:27
πηγή χρήστη

ψήφοι
15

Φαίνεται ότι η ώθηση :: static_vector είναι αυτό που ψάχνετε. Από τα έγγραφα:

static_vector είναι ένα υβρίδιο μεταξύ του διανύσματος και συστοιχίας: σαν φορέα, είναι ένα δοχείο αλληλουχίας με συνεχόμενο αποθήκευσης που μπορεί να αλλάξει ως προς το μέγεθος, μαζί με τη στατική κατανομή, χαμηλή επιβάρυνση, και σταθερή χωρητικότητα της διάταξης. static_vector βασίζεται στο Adam Wulkiewicz και υψηλής απόδοσης κατηγορίας varray Andrew Hundt του.

Ο αριθμός των στοιχείων σε ένα static_vector μπορεί να ποικίλλει δυναμικά μέχρι ένα σταθερό χωρητικότητα επειδή τα στοιχεία αποθηκεύονται μέσα στο ίδιο το αντικείμενο παρομοίως σε μία συστοιχία.

Απαντήθηκε 16/01/2014 στις 14:23
πηγή χρήστη

ψήφοι
11

Ορισμένες επιλογές μπορεί να θέλετε να δείτε:

STLSoft από τον Matthew Wilson (συγγραφέας του Ατελής C ++) έχει μια auto_bufferτάξη προτύπου που δίνει μια προεπιλεγμένη σειρά στη στοίβα, αλλά αν μεγαλώνει μεγαλύτερη από την κατανομή στοίβα θα αρπάξει τη μνήμη από το σωρό. Μου αρέσει αυτή η κατηγορία - αν γνωρίζετε ότι τα μεγέθη εμπορευματοκιβωτίων σας γενικά θα πρέπει να περιορίζεται από ένα μάλλον χαμηλό όριο, τότε θα έχετε την ταχύτητα ενός τοπικού, στοίβα διατεθεί σειρά. Ωστόσο, για τις γωνιά περιπτώσεις όπου χρειάζεται περισσότερη μνήμη, όλα εξακολουθεί να λειτουργεί σωστά.

http://www.stlsoft.org/doc-1.9/classstlsoft_1_1auto__buffer.html

Σημειώστε ότι η εφαρμογή χρησιμοποιώ και εγώ δεν είναι STLSoft, αλλά μια εφαρμογή που δανείζεται σε μεγάλο βαθμό από αυτό.

«Ο τεμπέλης προγραμματιστής» έκανε μια θέση για την υλοποίηση ενός δοχείου που χρησιμοποιεί alloca()για την αποθήκευση. Δεν είμαι οπαδός αυτής της τεχνικής, αλλά εγώ θα σας αφήσει να αποφασίσετε για τον εαυτό σας αν είναι αυτό που θέλετε:

http://tlzprgmr.wordpress.com/2008/04/02/c-how-to-create-variable-length-arrays-on-the-stack/

Στη συνέχεια υπάρχει boost::arrayτο οποίο έχει κανένα της δυναμικής συμπεριφοράς μέγεθος των δύο πρώτων, αλλά σας δίνει περισσότερο από το vectorπεριβάλλον από ό, τι ακριβώς χρησιμοποιώντας δείκτες όπως επαναλήπτες που έχετε με ενσωματωμένη συστοιχίες (δηλαδή, μπορείτε να πάρετε. begin(), end(), size(), Κ.λπ.):

http://www.boost.org/doc/libs/1_37_0/doc/html/boost/array.html

Απαντήθηκε 10/12/2008 στις 02:18
πηγή χρήστη

ψήφοι
4

Αν η ταχύτητα έχει σημασία, βλέπω τρέξει φορές

  • 4 ns int [10], σε σταθερό μέγεθος στη στοίβα
  • 40 ns <vector>
  • 1300 ns <stlsoft/containers/pod_vector.hpp>

για μία ηλίθια δοκιμή κάτω - μόλις 2 ώθηση, v [0] v [1], 2 ποπ, σε μία πλατφόρμα, Mac PPC, gcc-4.2 -O3 μόνο. (Δεν έχω ιδέα αν η Apple έχει βελτιστοποιηθεί STL τους.)

Να μην αποδεχθεί οποιαδήποτε χρόνοι δεν έχετε τον εαυτό σας φαλκιδεύεται. Και φυσικά κάθε τρόπο χρήσης είναι διαφορετική. Παρ 'όλα αυτά Παράγοντες> 2 έκπληξή μου.

(Αν MEMS, προσβάσεις μνήμης, είναι ο κυρίαρχος παράγοντας στην runtimes, τι είναι όλα τα επιπλέον MEMS στις διάφορες εφαρμογές;)

#include <stlsoft/containers/pod_vector.hpp>
#include <stdio.h>
using namespace std;

int main( int argc, char* argv[] )
{
        // times for 2 push, v[0] v[1], 2 pop, mac g4 ppc gcc-4.2 -O3 --
    // Vecint10 v;  // stack int[10]: 4 ns
    vector<int> v;  // 40 ns
    // stlsoft::pod_vector<int> v;  // 1300 ns
    // stlsoft::pod_vector<int, std::allocator<int>, 64> v;

    int n = (argv[1] ? atoi( argv[1] ) : 10) * 1000000;
    int sum = 0;

    while( --n >= 0 ){
        v.push_back( n );
        v.push_back( n );
        sum += v[0] + v[1];
        v.pop_back();
        v.pop_back();
    }
    printf( "sum: %d\n", sum );

}
Απαντήθηκε 29/07/2009 στις 12:20
πηγή χρήστη

ψήφοι
4

Μπορείτε να χρησιμοποιήσετε τη δική σας εκχώρησης για std φορέα :: και να το διαθέσουν κομμάτια της στοίβας που βασίζεται αποθήκευσης σας, παρόμοιο με το παράδειγμά σας. Η κατηγορία κατανεμητής είναι το δεύτερο μέρος του προτύπου.

Επεξεργασία: ποτέ δεν έχω δοκιμάσει αυτό, και κοιτάζοντας την τεκμηρίωση περαιτέρω με κάνει να πιστεύω δεν μπορείτε να γράψετε τη δική σας εκχώρησης. Είμαι ακόμη ψάχνει σε αυτό.

Απαντήθηκε 09/12/2008 στις 23:18
πηγή χρήστη

ψήφοι
3

TR1 :: σειρά ταιριάζει εν μέρει την περιγραφή σας. Στερείται τα πράγματα όπως push ___ πίσω (), κλπ, αλλά ίσως να αξίζει να ρίξουμε μια ματιά σε ως σημείο εκκίνησης. Αναδίπλωση του και την προσθήκη ενός δείκτη για την «πλάτη» για τη στήριξη push_back (), κ.λπ., θα πρέπει να είναι αρκετά εύκολο.

Απαντήθηκε 09/12/2008 στις 23:39
πηγή χρήστη

ψήφοι
2

Μπορεί να είναι η περίπτωση που χρησιμοποιείτε Qt. Τότε ίσως να θέλετε να πάτε για QVarLengthArray( docs ). Βρίσκεται κυρίως μεταξύ std::vectorκαι std::array, κατανομή στατικά για ένα ορισμένο ποσό και πέφτει πίσω στην κατανομή σωρού εάν είναι απαραίτητο.

Θα προτιμούσα την έκδοση ώθηση, αν ήμουν χρησιμοποιώντας όμως.

Απαντήθηκε 13/05/2014 στις 21:00
πηγή χρήστη

ψήφοι
2

Γιατί θέλετε να το βάλετε στην στοίβα ιδιαίτερα; Αν έχετε μια εφαρμογή των καταμε (), θα μπορούσε να buld μια τάξη εκχώρησης χρησιμοποιώντας ότι αντί της malloc (), αλλά η ιδέα σας χρησιμοποιώντας ένα στατικά κατανεμημένο πίνακα είναι ακόμα καλύτερο: είναι εξίσου γρήγορα στις περισσότερες αρχιτεκτονικές, και δεν το κάνετε διαφθοράς στοίβα κίνδυνο κάτι πάει στραβά.

Απαντήθηκε 09/12/2008 στις 23:25
πηγή χρήστη

ψήφοι
1

Boost έχει αυτό. Κάλεσε τους small_vector

small_vector είναι ένας φορέας που μοιάζει με δοχείο βελτιστοποιηθεί για την περίπτωση όταν περιέχει λίγα στοιχεία. Περιέχει μερικά συνέπεια, προχορηγηθέντες στοιχεία επί τόπου, η οποία του επιτρέπει να αποφευχθεί η χρήση της δυναμικής κατανομής αποθήκευσης, όταν ο πραγματικός αριθμός των στοιχείων είναι κάτω από αυτό το όριο συνέπεια, προχορηγηθέντες. small_vector είναι εμπνευσμένο από δοχείο SmallVector LLVM του. Σε αντίθεση με static_vector, χωρητικότητας small_vector μπορεί να αυξηθεί πέρα ​​από την αρχική συνέπεια, προχορηγηθέντες ικανότητα.

small_vector είναι μετατρέψιμες σε small_vector_base, έναν τύπο που είναι ανεξάρτητη από την καταμέτρηση συνέπεια, προχορηγηθέντες στοιχείο, επιτρέποντας κωδικός πελάτη που δεν χρειάζεται να templated σε αυτό το Ν επιχείρημα. small_vector κληρονομεί συναρτήσεις-μέλη όλων φορέα, ώστε να υποστηρίζει όλες τις βασικές λειτουργίες, όπως την τοποθέτησή τους, stateful κατανεμητές, κλπ

Απαντήθηκε 21/04/2016 στις 08:50
πηγή χρήστη

ψήφοι
0

Αν θέλετε να διαθέσει στην στοίβα, αλλά δεν θέλουν να προ-καθορίζουν το μέγιστο μέγεθος κατά τη μεταγλώττιση χρόνο, μπορείτε να χρησιμοποιήσετε StackVector , μια μικρή εφαρμογή που μπορεί να χρησιμοποιηθεί σαν αυτό:

new_stack_vector(Type, name, size)

όπου Typeείναι ο τύπος του στοιχείου στον φορέα, nameείναι το όνομα της μεταβλητής του φορέα, και sizeείναι ο μέγιστος αριθμός των στοιχείων για να επιτραπεί στον φορέα.

sizeμπορεί να είναι μεταβλητή και δεν χρειάζεται να είναι μια σταθερή μεταγλώττισης! :ΡΕ

Παράδειγμα:

new_stack_vector(int, vec, 100); //like vector<int> vec; vec.reserve(100); but on the stack :)
vec.push_back(10); //added "10" as the first item in the vector

...και αυτό είναι όλο!

Αποποίηση: Μη χρησιμοποιείτε ποτέ πολύ μεγάλα μεγέθη σειρά στη στοίβα εν γένει. Όπως και εσείς δεν θα πρέπει να χρησιμοποιήσετε int var[9999999], θα πρέπει ομοίως να μην χρησιμοποιήσει new_stack_vector(int, vec, 9999999)! Χρησιμοποιήστε υπεύθυνα.

Απαντήθηκε 07/03/2018 στις 13:27
πηγή χρήστη

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more