Bununla endişelenmek istemem. Bunu bir döngü içinde yaparsanız, dizeler yeniden tahsisleri en aza indirmek için her zaman belleği önceden tahsis eder - sadece operator+=
bu durumda kullanın . Ve manuel olarak yaparsanız, bunun gibi veya daha uzun
a + " : " + c
Sonra, derleyici bazı dönüş değeri kopyalarını eleyebilse bile geçiciler yaratıyor. Bunun nedeni, art arda çağrılmasında operator+
, referans parametresinin adlandırılmış bir nesneye mi yoksa bir alt çağırmadan geçici olarak döndürülen bir nesneye mi başvurduğunu bilmemesidir operator+
. İlk önce profil oluşturmadan endişelenmemeyi tercih ederim. Ama bunu göstermek için bir örnek alalım. Bağlamayı açıklığa kavuşturmak için önce parantez kullanıyoruz. Açıklık için kullanılan işlev bildiriminin hemen arkasına argümanları koyuyorum. Bunun altında, ortaya çıkan ifadenin ne olduğunu gösteriyorum:
((a + " : ") + c)
calls string operator+(string const&, char const*)(a, " : ")
=> (tmp1 + c)
Şimdi, bu ek olarak, tmp1
gösterilen argümanlarla + operatörüne yapılan ilk çağrı tarafından döndürülen şeydir. Derleyicinin gerçekten akıllı olduğunu ve dönüş değeri kopyasını optimize ettiğini varsayıyoruz. Bu yüzden concatenation içeren tek bir yeni dize ile bitirmek a
ve " : "
. Şimdi, bu olur:
(tmp1 + c)
calls string operator+(string const&, string const&)(tmp1, c)
=> tmp2 == <end result>
Bunu şununla karşılaştırın:
std::string f = "hello";
(f + c)
calls string operator+(string const&, string const&)(f, c)
=> tmp1 == <end result>
Aynı işlevi geçici ve adlandırılmış bir dizge için kullanıyor! Yani derleyici sahip olduğu için yeni bir dizeye ve ekleme yapılması halinde argüman kopyalayıp gövdesinden iade etmek operator+
. Bir geçicinin anısını alıp ona ekleyemez. İfade ne kadar büyükse, dizelerin o kadar çok kopyasının yapılması gerekir.
Sonraki Visual Studio ve GCC, c ++ 1x'in taşıma semantiğini ( kopya semantiğini tamamlayan ) ve deneysel bir ekleme olarak rvalue referanslarını destekleyecektir. Bu, parametrenin geçici olup olmadığını anlamaya izin verir. Bu, bu tür eklemeleri inanılmaz derecede hızlı hale getirecektir, çünkü yukarıdakilerin tümü kopyasız bir "eklenti hattı" ile sonuçlanacaktır.
Bir darboğaz olduğu ortaya çıkarsa, yine de yapabilirsiniz
std::string(a).append(" : ").append(c) ...
append
Çağrılar için argüman eklemek *this
ve daha sonra kendilerine bir başvuru döndürür. Yani orada geçicilerin kopyalanması yapılmaz. Veya alternatif operator+=
olarak kullanılabilir, ancak önceliği düzeltmek için çirkin parantezlere ihtiyacınız olacaktır.