Move semantics, C++'da nesneler arasında kaynakları kopyalamak yerine taşıyarak etkili bir şekilde aktarılmasını sağlayan bir mekanizmadır. C++11 ile birlikte tanıtılan hareketli yapıcılar ve atama operatörleri, nesnelerin kaynaklarını başka bir nesneye kopyalama maliyetine girmeden aktarmasına olanak tanır.
std::move, verilen nesneyi rvalue referansına dönüştürerek, kaynakların güvenli bir şekilde taşınabileceğini belirtir. std::forward, şablonlarda, değer türünü (lvalue/rvalue) daha ileriye aktarırken korumak için kullanılır.
#include <string> #include <vector> #include <iostream> std::vector<std::string> getNames() { std::vector<std::string> v = {"Alice", "Bob", "Charlie"}; return v; // Burada move semantics etkin olacaktır } int main() { std::vector<std::string> names = getNames(); // Burada getNames() içeriği eklenir, gereksiz kopyalama olmadan }
std::move ile hareketli yapıcı arasındaki fark nedir? std::move yazıldığında her zaman nesne taşınacak mı?
Cevap:
std::move, yalnızca rvalue referansına dönüşüm sağlar, kendi başına taşınmayı gerçekleştirmez. Hareketli işlem yalnızca gerçek bir hareketli yapıcı/operatör varsa gerçekleştirilecektir. Aksi takdirde kopyalama gerçekleşir.
struct A { A() = default; // hareketli yapıcı yok A(const A&) { std::cout << "Kopyala! "; } }; A a1; A a2 = std::move(a1); // Kopyalama çağrılır, taşıma olmaz
Tarih
-Bir finansal sistemde, dizgiler üzerindeki işi optimize etmek için kopyalamaları std::move ile değiştirdiler, ancak yapılandırma hareketli yapıcılar sağlamıyordu. Kopyalama devam etti, performans artışı olmadı ve kodun hızlandığına dair yanlış bir güven oluştu.
Tarih
-Geliştirici, taşıma işleminden sonra kullanmaya devam ettiği bir değişken üzerinde std::move() gerçekleştirdi. Veriler tutarsız bir durumda kaldı ve uygulama periyodik olarak çöktü.
Tarih
-Sunucu kütüphane kodunda, geçici nesneleri const referans ile aldılar ve ardından std::move() ile taşıma beklediler. Sonuç olarak, kopyalama gerçekleşti, verimsiz çalışma ve yüksek yük altında gecikmeler arttı.