C ++ STL-vektör sınıfı için görünümlü ama yığın depolama kullanarak

oy
44

Ben kendi yazmadan önce tüm millet soracaktır.

Neredeyse tam yığın bir diziye bir STL vektör ama mağazalarda verileri gibi bir C ++ sınıfına arıyorum. STL ayırıcı sınıfının çeşit da çalışmaya devam eder, ancak (onlardan biri benim ikinci seçim olsa da) yığın her türlü, hatta statik tahsis başına iplik yığın önlemek çalışıyorum. Yığın, sadece daha etkilidir.

Bu bir vektör kullanıldığı geçerli kodu yerine neredeyse bir damla olması gerekiyor.

Ben böyle bir şey düşünüyordum kendim yazmaya ne hakkında olduğunu İçin:

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

Veya sınıf tampon boşluk dahili olarak tahsis olabilir. Sonra gibi görünecektir:

stack_vector<match_item, 256> matches;

Bu hiç olmamalı rağmen, bu alan biterse eğer std :: bad_alloc atmak düşünüyordum.

Güncelleştirme

Chromium'un stack_container.h kullanarak harika çalışıyor!

Ben öyle yapmanın düşünmemişti sebebi kendim hep STL toplama yapıcıları için ayırıcı nesne parametresi gözardı olmasıdır. Ben statik havuzlar yapmaya şablon parametresini birkaç kez kullanmış ama kodu görmüş ya aslında nesne parametresi kullanılan herhangi bir yazılı asla. Ben yeni bir şey öğrendim. Çok havalı!

Kod biraz dağınık ve nedense GCC Vektörün ayırıcı parametresi içine inşa yerine gerçek bir kalem olarak allocator ilan etmeye zorladı. Böyle bir şey gitti:

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);

Buna:

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 );

Ve ben yenisini beyan zaman o tekrarlamak zorunda. Ama istediğim gibi çalışır.

Ben stack_container.h tanımlanan bir StackVector olduğunu fark ve bunu kullanarak çalıştı. Ama vektör devralan ya da bir drop-in yerine değildi aynı yöntemleri tanımlamaz. Ben bunu vazgeçtim yüzden vektörü kullanarak tüm kodu yeniden yazmak istemedim.

Oluştur 09/12/2008 saat 23:15
kaynak kullanıcı
Diğer dillerde...                            


10 cevaplar

oy
38

Sen tamamen yeni konteyner sınıfı yazmak gerekmez. Eğer STL kapları ile sopa, ama örnek için ikinci parametre değiştirebilir std::vectorit a yığın-tampon ayırır özel allocator vermek. Krom yazarlar sadece bunun için bir allocator yazdı:

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

Bu ne kadar büyük söylemek bir tampon ayırarak çalışır. Sen konteyner ve çağrıyı oluşturmak container.reserve(buffer_size);. Eğer bu boyutu taşar ise allocator otomatik (o türetilmiştir beri yığın elemanları alacak std::allocator, o durumda sadece standart ayırıcı imkanlarını kullanacaktır). Ben hiç denemedim, ama denemeye değer olduğunu düşünüyorum bu yüzden google gibi görünüyor.

Kullanımı şu şekildedir:

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;
Cevap 09/12/2008 saat 23:27
kaynak kullanıcı

oy
15

O görünüyor boost :: static_vector Aradığınız budur. Belgelerden;

static_vector vektörü ve dizi arasında bir hibrittir: vektör gibi, statik ayırma, düşük yük ve dizinin sabit kapasitesi ile birlikte, büyüklüğü değişmez bıtışik depolama alanı olan bir dizi kap var. static_vector Adam Wulkiewicz ve Andrew HUNDT en yüksek performanslı VARRAY sınıfına dayanmaktadır.

elemanlarının bir dizi benzer nesnenin kendisi içinde depolandığı için bir static_vector eleman sayısı sabit bir kapasiteye kadar dinamik değişebilir.

Cevap 16/01/2014 saat 14:23
kaynak kullanıcı

oy
11

Bazı seçenekler bakmak isteyebilirsiniz:

Matthew Wilson (Kusurlu C ++ yazarı) ile STLSoft bir sahiptir auto_bufferyığında varsayılan dizi koyar şablon sınıfı ama yığın dağılımı daha büyük olursa yığın bellek çekecek. Bu dersten gibi - Eğer konteyner boyutları genellikle oldukça düşük limitin sınırlanmış olacak biliyorum, o zaman, bir yerel hızını almak tahsis dizi yığını. Ancak, daha fazla bellek gerekir köşe durumlar için, tüm hala düzgün çalışır.

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

Kendimi kullanmak uygulama STLSoft en, ama bunun ağırca ödünç bir uygulama olmadığına dikkat edin.

"Tembel Programcı" kullanan bir kabın bir uygulama için bir yazı yaptım alloca()depolama için. Bu tekniğin bir hayranı değilim, ama istediğiniz buysa kendiniz için karar vereceğiz:

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

Sonra orada boost::arrayilk ikisinin dinamik boyutlandırma davranışı hiçbiri yoktur ki, ama size daha verir vectorsadece dahili diziler ile elde yineleyiciler olarak işaretçileri kullanmak yerine arayüzüne (yani sen olsun. begin(), end(), size()Vs.):

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

Cevap 10/12/2008 saat 02:18
kaynak kullanıcı

oy
4

hız konularda, koşmak kez bakın

  • 4ns int [10] yığında, sabit boyutlu
  • 40 ns <vector>
  • 1300 ns <stlsoft/containers/pod_vector.hpp>

altında bir aptal test için - sadece 2 itme, T [0] f [1], 2 açılır, bir platform, Mac ppc, GCC-4,2 -O3 sadece. (Apple kendi stl optimize varsa hiçbir fikrim yok.)

Kendini sahte varsa bunlara zamanlamaları kabul etmeyin. Ve tabii her kullanım desen farklıdır. Yine de> 2 sürpriz beni faktörler.

(Mems, hafıza erişirse, çeşitli uygulamalarda tüm ekstra mems ne çalıştırıcıları, baskın faktör?)

#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 );

}
Cevap 29/07/2009 saat 12:20
kaynak kullanıcı

oy
4

Sen std :: vector için kendi ayırıcısı kullandıkları ve senin örneğe benzer destenizin tabanlı depolama parçalarını, tahsis olabilir. allocator sınıfı şablonun ikinci kısmıdır.

Düzenleme: Bunu denedim, ve dokümantasyon bakarak daha da kendi ayırıcı yazamam beni inandıramaz hiç. Hala araştırıyorum.

Cevap 09/12/2008 saat 23:18
kaynak kullanıcı

oy
3

tr1 :: Dizi kısmen açıklamanızı eşleşir. O, vb () geri itme gibi şeyler ___ yoksun, ama bir başlangıç ​​noktası olarak bir göz alarak değer olabilir. Vb onu tamamlayan ve) push_back (destekleyecek "arka" bir endeks ekleyerek oldukça kolay olmalıdır.

Cevap 09/12/2008 saat 23:39
kaynak kullanıcı

oy
2

Bu Qt kullandığınız durumda olabilir. Sonra sen gitmek isteyebilirsiniz QVarLengthArray( docs ). Bu arasında temel olarak oturur std::vectorve std::arraybelirli bir süre için statik ayrılması ve gerektiğinde yığın ayırma geri düşme.

Ben olsa kullandıysa ben artırmak versiyonunu tercih ediyorum.

Cevap 13/05/2014 saat 21:00
kaynak kullanıcı

oy
2

Neden koymak istiyoruz yığını özellikle? O kadar hızlı çok mimari sadece, ve bunun dışındaki: alloca () bir uygulamasını varsa, bunun yerine malloc (), ancak statik olarak ayrılmış bir dizi kullanmanın fikrinizi bile iyidir kullanarak bir sınıf ayırıcısı buld olabilir Bu karmaşa kadar riski yığın bozulması.

Cevap 09/12/2008 saat 23:25
kaynak kullanıcı

oy
1

Boost bu var. Onun adı verilen small_vector

small_vector çok az sayıda öğeleri içeren durum için optimize edilmiş bir vektör gibi bir kaptır. Bu elemanların gerçek sayısı, bu önceden tahsis edilen alanlara eşiğin altında olduğunda dinamik depolama ayırma kullanımını önlemek için sağlar, yerinde bazı önceden tahsis edilen alanlara elemanları içerir. small_vector LLVM en SmallVector konteyner esinlenmiştir. static_vector aksine, small_vector kapasitesi başlangıçtaki önceden tahsis edilen alanlara kapasitesinin ötesinde büyüyebilir.

small_vector, o N argüman üzerinde şablon bir gerekmez istemci kodunu sağlayan önceden tahsis edilen alanlara eleman sayısından bağımsız bir tür small_vector_base dönüşebilmektedir. o vb yerleşme, durum bilgisi allocators, gibi tüm standart özellikleri destekler, böylece small_vector tüm Vektörün üye işlevlerini devralır

Cevap 21/04/2016 saat 08:50
kaynak kullanıcı

oy
0

Eğer yığın ayırmaya ama derleme sırasında maksimum boyutu önceden tanımlamak istemiyorsanız istiyorsanız, kullanabileceğiniz StackVector , bu gibi kullanılabilir küçük uygulama:

new_stack_vector(Type, name, size)

burada Typevektör içinde eleman türüdür, namevektörün değişken adım ve sizeunsurların maksimum sayıda vektöründe sağlamaktır.

sizedeğişken olabilir ve derleme zamanı sabiti olması gerekmez! : D

Örnek:

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

...ve hepsi bu!

Uyarı: Genel olarak yığında çok büyük dizi boyutları kullanmayın. Eğer kullanmamalısınız gibi int var[9999999], sen benzer kullanmamalısınız new_stack_vector(int, vec, 9999999)! Sorumlu kullanın.

Cevap 07/03/2018 saat 13:27
kaynak kullanıcı

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