2016-03-25 24 views
5

std::move ve std::forward arasındaki ayrım iyi bilinir, iletilen bir nesnenin değer kategorisini korumak için ikincisini kullanırız ve hareket semantiğini etkinleştirmek için yeniden referansa yayınlanacak olanları kullanırız. ++ etkili Modern C'deNeden std :: forward kullanmıyorsunuz?

, bir kılavuz var olduğunu devletler

rvalue referanslar, evrensel referanslara std::forward üzerinde kullanım std::move. a bir yönlendirme referansı ancak basit rvalue referans değil (biz değer kategorisini değiştirmek istemiyorum ve senaryolar)

aşağıdaki senaryoda Oysa

,

template <class T> 
void f(vector<T>&& a) 
{ 
    some_func(std::move(a)); 
} 

, kalmasın diye Aşağıdakileri yapmak tam olarak aynı mı? Bu yana

template <class T> 
void f(vector<T>&& a) 
{ 
    some_func(std::forward<decltype(a)>(a)); 
} 

kolayca

#define FWD(arg) std::forward<decltype(arg)>(arg) 

hep şöyle bu makro tanımını kullanmak daha uygun değil, böyle bir makro içinde muhafaza edilebilir?

void f(vector<T>&& a) 
{ 
    some_func(FWD(a)); 
} 

Tam olarak eşdeğer yazmanın iki yolu değil mi?

+3

Makro çözümünü 'move()' yazmasından daha uygun olarak görüntülemede sorun yaşıyorum ...ama bu bana fikir temelli bir soru olarak vuruyor. Her ikisi de – Barry

+3

aynı şeyi yapar ama bir kez argüman düzenli bir referanstır ve vektörü taşımak istersiniz. iletmeyi kullanmaya devam et, –

+0

@Barry'nin eşdeğerde onayı olmasını istedim, bunun için de thnx. Düşüncelere dayalı olup olmadığına, sadece bir programlama stilini savunmanın önyargıya işaret etmediğine, birisinin bunu yapmak için çok iyi nedenlere sahip olabileceğine (ve onlarla ilgili ayrıntılı bilgi verebileceklerine) katılıyorum. –

cevap

6

Eh. Tartışmaya açık. Özel örneğinizde buna eşdeğerdir. Ama bunu bir alışkanlık haline getirmezdim. Bunun bir nedeni, yönlendirme ve taşıma arasında anlamsal bir ayrım yapmaktır. Bir başka neden ise, tutarlı bir API'ye sahip olmanızın 'a ek olarak MOV'a sahip olmanız ve gerçekten de kötü görünmesi ve hiçbir şey yapmamasıdır. Daha da önemlisi, kodunuz beklenmedik şekilde başarısız olabilir. Sadece FWD değiştirirseniz,

Ancak

#include <iostream> 

using namespace std; 

#define FWD(arg) std::forward<decltype(arg)>(arg) 

struct S { 
    S() { cout << "S()\n"; } 
    S(const S&) { cout << "S(const S&)\n"; } 
    S(S&&) { cout << "S(S&&)\n"; } 
}; 

void some_func(S) {} 

void f(S&& s) 
{ 
    some_func(FWD(s)); 
} 

int main() 
{ 
    f(S{}); 
} 

Bu

S()
S yazdırır (S & &):

Aşağıdaki kodu düşünün Başka bir (isteğe bağlı olarak) parantez çifti eses, örneğin:

void f(S&& s) 
{ 
    some_func(FWD((s))); 
} 

Şimdi

S()
S (const S &)

olsun Ve şimdi bir de decltype kullandığınız için bu Bir değer referansına değerlendiren ifade.

+0

İyi puanlar yaratıyorsunuz. Ancak parantez için "görünüşte isteğe bağlı" karakterizasyonuna katılmıyorum. Eğer biri "decltype" ile çalışıyorsa [bu şeyi] bilmeliyiz (http://stackoverflow.com/a/17242295/4224575) ve bu bir hata bile 'std :: forward

+2

@Lorah Evet, ama bu bir makro - hemen 'decltype' kullandığını göremezsiniz. – Barry

+0

@Barry Eğer bir fonksiyon olsaydı ne yaptığını görmezsiniz, her zaman kodu okumalısınız; Çoğunlukla, makroları okuduğumda, "okuduğum bir yan etki veya mutasyon mutasyonu" gibi kodları okuduğumda bile "şeffaflık eksikliği" ni anladım. Ben FWD gibi metinsel değiştirme (örneğin çift değerlendirme, tesadüfi veri yapıları, gizli kontrol akışı yok) gibi nedenlerle bir makro kullanmıyorum. Lütfen [bu] 'a bir göz atabilir misiniz (http://stackoverflow.com/q/36230428/4224575)? (konu dışı ama biraz yardım edebilirim) –

İlgili konular