STL

2010-10-07 35 views
33

kullanarak skaler bir değerle çarpma vektör elemanları Merhaba Ica (çarpma, ekleme, vb) vektörü skaler değere göre myv1 * 3 olarak istiyorum, biliyorum bir forloop ile bir işlev yapabilirim, ancak bunu yapmanın bir yolu var mı STL işlevini kullanarak? {Algorithm.h :: transform işlevi} gibi bir şey mi?STL

cevap

73

Evet,:

std::transform(myv1.begin(), myv1.end(), myv1.begin(), 
       std::bind1st(std::multiplies<T>(),3)); 
+0

Teşekkürler çok dahidir! –

21

vector yerine valarray kullanırsanız, bir skalar çarpma yapmak için yerleşik operatörler vardır.

transform(v.begin(), v.end(), v.begin(), _1 * 3); 

(Eğer kolayca gibi anonim işlev nesneleri oluşturmanıza olanak sağlar Boost.Lambda benzer bir şey var varsayarak: Bir vector kullanmak zorunda ise

v *= 3; 

, gerçekten işi yapmak için transform kullanabilirsiniz _1 * 3 :-P) std::transform kullanılarak

+1

Valarrays, doğru çözüm IMO'dur. Şansınızla, uygulamanız prosedürü uygulamak için SSE talimatlarını kullanır ve bu da onu çok daha hızlı hale getirir. Böyle bir valarray uygulaması için http://www.pixelglow.com/macstl/valarray/ adresine bakın. Ne yazık ki, çok yaygın değil, bu yüzden SSE komutlarının avantajlarını istiyorsanız, muhtemelen derleyici içsel kullanmanız gerekecek ... – Dragontamer5788

+0

@Dragon: 'valarray' en iyi STL çözümü, ancak yüksek performans için çok iyi değil Bilgiyi, bellekte çok fazla veri kopyalama eğiliminde olduğundan ve zayıf bellek erişim düzenine sahip olan tekli işlemleri içeren küçük döngülerden oluşan diziler üretir. Yine de, valarray'dan uygun bir ifade şablon sistemine yükseltmek daha kolaydır. – Potatoswatter

0

Yalnızca: Verilerinizi sabit boyutlu bir dizide (float değerleri [N]) alabilirseniz, SSE intrinsics'i daha hızlı yapmak için kullanabilirsiniz.

0

Bu STL'yi istediğiniz kadar tanımadığımı biliyorum, ancak farklı ihtiyaçlara göre uyarlayabileceğiniz bir şey.

Hesaplamak için kullanabileceğiniz bir şablon aşağıdadır; 'func' yapmak istediğiniz işlev olacaktır: çarpın, ekleyin ve benzeri; 'parm', 'func' için ikinci parametredir. Farklı func'leri farklı türlerde daha fazla parkeyle çekmek için bunu kolayca genişletebilirsiniz.

template<typename _ITStart, typename _ITEnd, typename _Func , typename _Value > 
_ITStart xform(_ITStart its, _ITEnd ite, _Func func, _Value parm) 
{ 
    while (its != ite) { *its = func(*its, parm); its++; } 
    return its; 
} 
... 

int mul(int a, int b) { return a*b; } 

vector<int> v; 

xform(v.begin(), v.end(), mul, 3); /* will multiply each element of v by 3 */ 

Ayrıca, bu bir 'güvenli' işlev değil, yapmanız gereken tip/değer denetimi vb kullanmadan önce. Bu durumda basit bir lambda yeterli olacaktır, bazı şablona göre bir vektör çapraz ve her eleman manipüle etmek istediğimde for_each düşünüyorum

+0

Bu çalışır, ancak aslında 'std :: transform' zaten sizin için bunu yapar gibi, tekerleği yeniden icat ediyor. –

+0

Evet - kabul edilen cevapta gördüm ... ama aslında işe yarayan bir tekerleği yeniden icat etmenin ne kadar mutlu olduğunu biliyor musunuz?) Her neyse kendimi bir konformist haline geldiğimde çekeceğim;) – slashmais

0

çok apt:

std::for_each(myv1.begin(), mtv1.end(), [](int &el){el *= 3; }); 

notu o yakalamak istediğiniz herhangi değişken lambda fonksiyonunun kullanılması için (örneğin önceden belirlenmiş skaler ile çarpmak istediğinizi söyleyin), referans olarak brakete girer.

+0

Bu amaç değil. std :: for_each'. std :: for_each, bazı (muhtemelen durum bilgisi olan) işlev nesnesini bir aralığa uygular ve bu işlev nesnesini döndürür. Bir aralığı dönüştürmek istiyorsanız, amacınızı daha net hale getirmek için 'std :: dönüşümü' kullanın. – sv90