@ JDługosz'un yorumlarda belirttiği gibi, Herb başka bir konuşmada (daha sonra?) Başka tavsiyeler verir, kabaca buradan bakın: https://youtu.be/xnqTKD8uD64?t=54m50s .
Onun tavsiyesi f
, yapıyı bu havuz argümanlarından taşıyacağınızı varsayarak, yalnızca havuz argümanları alan bir fonksiyon için değer parametrelerini kullanmaya dayanır.
Bu genel yaklaşım, f
sırasıyla lvalue ve rvalue argümanlarına göre uyarlanmış optimal bir uygulama ile karşılaştırıldığında, hem lvalue hem de rvalue argümanları için bir hareket yapıcısının ek yükünü ekler . Bunun neden böyle olduğunu görmek için , bir copy f
parametresi aldığını varsayalım , burada T
bazı kopyalama ve taşıma yapıcı türü:
void f(T x) {
T y{std::move(x)};
}
çağrı f
Bir değer bağımsız değişkeni ile çağrıldığında, bir kopya oluşturucunun kurulax
ve bir hareket kurucusunun da kurmaya sonuçlanır y
. Öte yandan, f
bir rvalue argümanı ile çağrılmak bir hareket kurucusunun inşa edilmesine x
ve başka bir hareket kurucusunun inşaa çağrılmasına neden olury
.
Genel olarak, f
lvalue argümanlarının optimum uygulaması aşağıdaki gibidir:
void f(const T& x) {
T y{x};
}
Bu durumda, yalnızca bir kopya oluşturucu oluşturmaya çağrılır. y
. f
Değerleme argümanlarının optimal uygulaması yine genel olarak şu şekildedir:
void f(T&& x) {
T y{std::move(x)};
}
Bu durumda, yalnızca bir hamle yapıcısı y
.
Bu nedenle mantıklı bir uzlaşma, bir değer parametresi almak ve optimal uygulama ile ilgili lvalue veya rvalue argümanları için ekstra bir hareket oluşturucu çağrısı yapmaktır, bu da Herb'in konuşmasında verilen tavsiyedir.
@ JDługosz'un yorumlarda belirttiği gibi, değere göre geçmek sadece lavabo argümanından bir nesne oluşturacak fonksiyonlar için anlamlıdır. f
Bağımsız değişkenini kopyalayan bir işleve sahip olduğunuzda, değere göre by-pass yaklaşımı, genel-by-const-referans yaklaşımından daha fazla ek yüke sahip olacaktır. f
Parametresinin bir kopyasını saklayan bir fonksiyonun değer bazında yaklaşımı şu şekle sahip olacaktır:
void f(T x) {
T y{...};
...
y = std::move(x);
}
Bu durumda, bir kopya yapısı ve bir değer bağımsız değişkeni için bir taşıma ataması ve bir değer bağımsız değişkeni için bir taşıma yapısı ve taşıma ataması vardır. Lvalue argümanı için en uygun durum:
void f(const T& x) {
T y{...};
...
y = x;
}
Bu, yalnızca kopya oluşturucudan artı değer-değeri yaklaşımı için gereken taşıma atamasından çok daha ucuz olan bir atamaya kadar kaynar. Bunun nedeni, atamanın mevcut ayrılan belleği yeniden kullanabilmesidir.y
ve bu nedenle (de) ayırmayı önleyebilmesidir, oysa kopya oluşturucu genellikle belleği tahsis edecektir.
Bir rvalue argümanı için f
, bir kopyayı muhafaza eden en uygun uygulama şu şekildedir:
void f(T&& x) {
T y{...};
...
y = std::move(x);
}
Yani, bu durumda sadece bir hareket ödevi. f
Bir const başvurusu alan sürümüne bir rvalue iletmek , bir taşıma ataması yerine yalnızca bir atamaya mal olur. Yani nispeten konuşursak,f
bu durumda genel uygulama olarak bir const referansı alma tercih edilir.
Bu nedenle, genel olarak, en uygun uygulama için, konuşmada gösterildiği gibi aşırı yükleme veya bir tür mükemmel yönlendirme yapmanız gerekir. Dezavantajı, f
argümanın değer kategorisinde aşırı yüklemeyi seçmeniz durumunda parametre sayısına bağlı olarak, gerekli aşırı yük sayısında bir kombinasyon patlamasıdır . Mükemmel yönlendirme, f
sanallaştırmayı önleyen bir şablon işlevi haline gelen dezavantaja sahiptir ve % 100 doğru elde etmek istiyorsanız önemli ölçüde daha karmaşık bir kodla sonuçlanır (kanlı ayrıntılar için konuşmaya bakın).