2012-06-16 10 views
5

C++ 11'den önce, büyük nesneler üzerinde çalışan bir işlevim varsa, içgüdü, bu tür bir prototip ile işlev yazmak olurdu.C++ 11'de, bir fonksiyonun çıktısını kabul edecek bir nesneye referansta geçmek için hala bir ihtiyaç var mı?

void f(A &return_value, A const &parameter_value); 

, C++ 11 yılında

(Burada, dönen_değer. A kopyalamak için büyük ve pahalı sadece bazı sınıftır. Işlevin çıktısını alacak sadece boş bir nesnedir) alarak hareket semantik avantajı, varsayılan öneri (Anladığım kadarıyla) daha basittir:

A f(A const &parameter_value); 

bunu eski şekilde yapmaya ihtiyaç dönen değeri bir nesne geçirmeden hala hiç var mı?

+1

Varsayılan öneri her zaman "uygun olanı yap ve gerekli bulursanız yoldan çık" olduğunu düşündüm ... – Mehrdad

+3

Böyle bir gereksinim olmadı, http://cpp-next.com/ adresine bakın. arşivi/2009/08/want-speed-pass-by-value/ –

+0

@ K-ballo: Standartlara ihtiyaç vardı (insanlar bunu kabul etmese de, C++ standardize edilmeden yaklaşık 20 yıl önce vardı) . Belki de olmasa da, C++ 'yı standardizasyon zamanı hakkında öğrenmeye yeni başlamıştım (ve o zamanlar bunun gerçekleştiğini bile bilmiyordum), standarttan önce kopya eliti diye bir şey var mıydı? Popüler derleyiciler tarafından kullanılmış mıydı? –

cevap

7

Diğerleri, A'un ucuz bir hareket ettiricisinin bulunamayacağı bir durumdadır. Senin A'unun yaptığını farz ediyorum.

A Eğer vector veya string gibi bazı tip ve o "dışarı" parametresi zaten hafıza gibi kaynaklara (sahip olduğu bilinmektedir: Ama bir "dışarı" parametresinde geçirmek isteyebilirsiniz bir daha durum hala) f içinde yeniden kullanılabilir, o zaman eğer bu kaynak yeniden kullanmak mantıklı. Örneğin göz önünde bulundurun:

void get_info(std::string&); 
bool process_info(const std::string&); 

void 
foo() 
{ 
    std::string info; 
    for (bool not_done = true; not_done;) 
    { 
     info.clear(); 
     get_info(info); 
     not_done = process_info(info); 
    } 
} 

vs: İlk durumda

std::string get_info(); 
bool process_info(const std::string&); 

void 
foo() 
{ 
    for (bool not_done = true; not_done;) 
    { 
     std::string info = get_info(); 
     not_done = process_info(info); 
    } 
} 

, döngü yürütür ve bu kapasitesi, daha sonra, potansiyel olarak döngünün her tekrarında yeniden gibi string içine inşa edecek kapasite . İkinci durumda, her yinelemede yeni bir string tahsis edilir (küçük dizge optimizasyon tamponunun ihmal edilmesi).

Artık bu, std::string değerini hiçbir zaman iade etmemelisiniz.Sadece bu sorunun farkında olmalı ve duruma göre mühendislik kararını uygulamalısınız.

3

Bir nesnenin kopyalamak için büyük ve pahalı olması, olması ve kopyalamasında semantiklerin ilerleyememesi mümkündür.

struct A { 
    std::array<double,100000> m_data; 
}; 

sizin nesneleri bu şekilde tasarlamak için iyi bir fikir olmayabilir, ancak nedense bu tip bir nesne varsa ve verileri doldurmak için bir işlev yazmak isterseniz o zaman belki: düşünün Bir out param kullanarak yapmak.

+1

Bir çıkış parametresi kullanmayı düşünebilirim, ama sadece bunların çoğunu yığına ayırmak istemediğim için. Bir nesnenin işlev döndürme değerinden yapılandırılması, herhangi bir aklı derleyicide olduğu kadar ucuzdur. –

+0

@ eq-: Kimsenin bunu yığından ayırmanızı istemez, 'new f() 'kesinlikle kabul edilebilir. –

+0

@matthieum. Bir işlev bir nesneyi değer olarak döndürdüğünde, by-pass yığın ayırmanın bir yolu yoktur. –

3

Bu şu anlama gelir: derleyiciniz geri dönüş değeri optimizasyonunu destekliyor mu ve sizin derleyici desteklerinizi RVO'yu kullanabilmeniz için tasarlanmış f işleviniz mi? Eğer öyleyse, o zaman, evet, her şeyden öte değere geri dönün. Değişken bir parametre ileterek hiçbir şey elde edemezsiniz ve bu şekilde yaparak çok sayıda kod netliği kazanırsınız. Eğer değilse, o zaman A'un tanımını araştırmalısınız.

Bazı türlerde hareket, kopyadan başka bir şey değildir. A aslında hareket etmeye değer bir şey içermiyorsa (sahiplik ve benzeri aktarımlar), o zaman hareket ederek bir şey elde edemezsiniz. Her şeyden sonra bir hareket serbest değildir; Bu, orijinalin sahip olduğu herhangi bir şeyin kopyaya aktarıldığını bilen bir kopyadır. Eğer tür bir şeye sahip değilse, o zaman bir hareket sadece bir kopyadır.

İlgili konular