2009-10-19 28 views
9

std::streambuf* alan bir istek yöntemiyle bir ağ istemcim var. Bu yöntem, boost::iostreams::copy tarafından, verileri bir ağ API'sine nasıl yazılacağını bilen, özel bir std::streambuf türetilmiş sınıf tarafından uygulanmaktadır. Bu, bir dosyayı belleğe okumaya gerek kalmadan istek üzerine aktarabilirim anlamına gelir. Ancak, bir dosyada olmayan büyük veri bloklarının gönderilmesi gereken bazı durumlar vardır, bu yüzden bir dizge içeren bir aşırı yük dahil ettim. Akıştaki tüm ağ kodlarını çoğaltmaktan kaçınmak için, dizeyi temsil eden bir streambuf kurmalı ve diğer yöntemi çağırmalıyım.Std :: string'ten bir kopyasını oluşturmadan akış?

std::istringstream ss(data); 
send(ss.rdbuf()); 

Maalesef istringstream bazı durumlarda birkaç megabayt olan verilerin, bir kopyasını yapar: Ben bu işi yapmak için anlamaya tek yolu gibi bir şey oldu. Genel durumda mükemmel bir anlam ifade eder, tabii ki, eğer bir nesneye bir referans gönderirseniz, o nesneyi o referansı kullanmaya devam edeceğini varsaymak istemezsiniz.

struct zerocopy_istringbuf 
    : public std::stringbuf 
{ 
    zerocopy_istringbuf(std::string const* s) 
     : std::stringbuf(std::ios::in) 
    { 
     char* p = const_cast<char*>(s->c_str()); 
     setg(p, p, p + s->length()); 
    } 
}; 

... 

send(&zerocopy_istringbuf(data)); 

Bu sadece iyi iş gibi görünüyor, ama bu gerçekten gerekli mi acaba:

aşağıdaki ile bu çalıştı. std::istringstream neden std::string const * numaralı telefonu kullanıyor? Bunu yapmanın daha iyi bir yolu var mı?

cevap

4

Bu sorunla karşılaşmanızın nedeni, std :: string'in yaptığınız işe gerçekten uygun olmamasıdır. Daha iyi bir fikir, ham verilerden geçerken char vektörünü kullanmaktır. Mümkünse, vektörü kullanmak için her şeyi değiştiririm, vektör :: swap ve vektörleri tüm kopyalamalarınızı ortadan kaldırmak için uygun olarak kullanır. Iostreams/streambuf api'yi seviyorsanız veya bir streambuf alan bir şeyle uğraşmak zorundaysanız, sizinki gibi bir vektör kullanan kendi streambuf'unuzu yaratmanız önemsiz olacaktır. Diğer cevaplarda listelenen aynı konularla aynı şeyi yapardı, ancak sınıfın sözleşmesini ihlal etmezsiniz. Aksi takdirde, elinizde olan şey, muhtemelen her yerde bir istringstream'den geçmenin en iyi yoludur.

+0

ilginç bir fikir. Mevcut kurulumla ilgili hoşuma giden şeylerden biri, std :: stringbuf'dan türeterek özel bir girdi veya çıktı akışı oluşturabilmem ve sadece bir veya iki basit işlevi, alt akışı veya "taşma" ve sync', temel sınıf benim için tüm tampon yönetimini yönetir. Sanırım şeyleri std :: vector'ya dayandırmak çok daha fazla koda ihtiyacım var demektir. Yine de "swap" ı kullanabiliyordum, ancak arayanın sabit bir referansta geçmekten ziyade "pes etmesini" istiyorum. –

2

imho, en iyi seçim kaldırılmış bir sınıf std :: strstream

+0

Teşekkürler, bunu bilmiyordum. Tek sorun, 'const char *' yerine bir 'char *' istediği, ancak bu işe yarayacak kadar kolay olmasıdır. –

İlgili konular