Taşıma semantiği nedir?
Ben sadece Yazılım Mühendisliği radyo podcast interview with Scott Meyers C 0x ile ilgili dinleme bitirdi. Yeni özelliklerin çoğu bana mantıklı geldi, ve aslında şimdi C 0 x, biri hariç heyecanlıyım. Ben hala alamadımtaşıma semantiği... Ne tam olarak?
CEVAP
En kolay örnek kod ile hareket semantiği anlamak benim için zor. Hadi sadece öbek ayrılan bellek bloğu: bir işaretçi tutan çok basit bir string sınıfı ile Başlat
#include <cstring>
#include <algorithm>
class string
{
char* data;
public:
string(const char* p)
{
size_t size = strlen(p) 1;
data = new char[size];
memcpy(data, p, size);
}
Bellek kendimizi yönetmek için seçtik beri rule of three takip etmeliyiz. Atama operatörü yazma erteleme ve sadece şimdi için yıkıcı ve kopya yapıcı uygulamak için gidiyorum:
~string()
{
delete[] data;
}
string(const string& that)
{
size_t size = strlen(that.data) 1;
data = new char[size];
memcpy(data, that.data, size);
}
Kopyalama kurucusu string nesneleri kopyalamak için ne anlama geldiğini tanımlar. Parametre const string& that
aşağıdaki örneklerde kopyaları yapmanızı sağlar hangi tür dize tüm ifadeler için bağlar:
string a(x); // Line 1
string b(x y); // Line 2
string c(some_function_returning_a_string()); // Line 3
Şimdi hareket semantiği içine anahtar bakış. Not yalnızca ilk satırını nerede anlaşıldı x
bu derin kopyasını gerçekten gerekli, çünkü biz belki incelemek x
sonraki ve çok da şaşırdım x
değişti bir şekilde. Dedim x
üç kez (eğer bu cümleyi sayarsak dört kez) ve ne kadar fark ettinizaynı nesneher zaman? x
gibi ifadeler "diyoruz". lvalues
Satır 2 ve 3 değişkenleri temel string nesneleri isim yok çünkü lvalues, ama rvalues değil, istemci yine zaman içinde daha sonraki bir noktada onları incelemek için bir yol vardır.
rvalues sonraki noktalı virgül (daha doğrusu: lexically bu rvalue içeren tam ifade) sonunda yok olan geçici nesneleri göstermek. Bu b
c
, başlatma sırasında kaynak dizesi ile istediğimiz her şeyi yapabiliriz çünkü . önemlidir ^em>istemci bir fark göremedim!
C 0x yeni bir mekanizma "olan, diğer şeyler arasında,başvuru" rvalue tanıttı bize fonksiyon aşırı yükleme ile rvalue bağımsız değişkenleri tespit etmek için izin verir. Tek yapmamız gereken rvalue reference parametresi ile bir kurucu yazmak. Sınıf içinde yapabilirizbir şey istiyoruzkaynak, içinde gidiyoruz sürecebazıgeçerli durum:
string(string&& that) // string&& is an rvalue reference to a string
{
data = that.data;
that.data = nullptr;
}
Burada ne yaptık? Derin yığın veri kopyalamak yerine, sadece işaretçiyi bir kopyasını aldık ve sonra özgün işaretçi null olarak ayarlayın. Sonuç olarak, "" başlangıçta kaynak dizesi. ait veri çaldık Yine, anahtar fikir olabilir hiçbir koşul altında müşteri kaynağı değiştirilmiş olduğunu tespit eder. Gerçekten bir kopyasını burada yapmayız beri, bu yapıcı "diyoruz". hareket kurucu Onun işi onları kopyalamak yerine başka bir nesneden kaynakları taşımaktır.
Tebrikler, artık hareket semantiği temellerini anlamak! Devam atama operatörünü uygulayarak izin verin. Eğer aşina değilseniz, 32**, Öğren ve Başar C-bir deyim istisna güvenliği ile ilgili, çünkü geri gel.
string& operator=(string that)
{
std::swap(data, that.data);
return *this;
}
};
Ha, bu kadar mı? "Nerede rvalue başvuru var?" diye sorabilirsiniz. "Burada ihtiyacımız yok" cevabım :)!
Parametre that
geçiyoruz unutmayındeğeryani that
sadece başka bir dize nesne gibi başlatılması gerekiyor. Tam olarak nasıl that
başlatılmış olacak? C 98 eski zamanlarda bir cevap olurdu "kopya yapıcı tarafından". C 0 x, derleyici atama operatörü değişken bir lvalue veya bir rvalue olup olmamasına göre kopya Kurucu ve kurucu arasında seçer.
Eğer öyleyse dediğin a = b
kurucu kopyalayınthat
başlatılacaktır ifade b
bir lvalue (çünkü), ve atama operatörü taze oluşturulan, derin bir kopyasını içeriğini değiştirir. -- Bir kopyasını yapmak, kopyasını içeriğini değiştirin ve sonra kapsam bırakarak kopyasını kurtulmak kopyalama ve takas deyim tanımı. Yeni bir şey yok burada.
Ama eğer a = x y
, diyorsanızyapıcı hareketthat
başlatılacaktır 26 ** ifadesi bir rvalue (çünkü), hiç bir derin kopyasını dahil, sadece etkili bir hareket yoktur.
that
hala inşa önemsiz olduğunu fakat bu tartışma, bağımsız bir nesnedir
yığın veri kopyalanacak olmadığı için hareket etti. x y
bir rvalue çünkü kopyalamak için gerekli değildi, ve yine, string nesneleri rvalues ile belirtilen yere gitmek sorun değil.
Özetlemek gerekirse, kopya yapıcı kaynağı kalması gerekir, çünkü derin bir kopyasını yapar. Hareket yapıcı, diğer yandan, sadece işaretçi kopyalayın ve sonra da boş bir kaynak işaretçisi ayarlayın. Tamam "" kaynak istemci nesnenin yeniden inceleme yolu vardır çünkü bu şekilde nesne. iptali için
Bu örnek üzerinde ana noktası var umuyoruz. Ben çok isteyerek terk eden rvalue başvuruları ve hareket semantiği daha basit tutmak için var. Eğer daha fazla ayrıntı istiyorsanız lütfen my supplementary answer bkz.
Taşıma semantiği ve işlevi sipariş değ...
İyi bir oturum tek ana bilgisayar node...
&Quot nedir; " (artı işareti) CSS...
En kısa algılayabileceği uygulama yanı...
&Quot;doğru" Ruby bir dizi sokman...