C++ Move Semantics – The Complete Guide İnceleme

Özet

Bu kitapta C++11 ile dile eklenen taşıma semantiği (move semantics) ve onun uygulamaları geniş bir şekilde anlatılmaktadır. İlk parçada taşıma semantiği ile ilgili temel kavramlar, taşıma semantiğinin faydaları, taşınan nesnelerin durumları, "noexcept" ile taşıma semantiğinin ilişkisi, değer kategorileri (value categories) gibi konular örneklerle ele alınmaktadır. İkinci parçada ise taşıma semantiğinin şablonlar (template) ile kullanımı ve uygulamaları ele alınmaktadır. Son parçada C++ Standart Kütüphanesi ile taşıma semantiği ilişkisi incelenmektedir.

İnceleme

Parça 1: Basic Features of Move Semantics (Taşıma Semantiğinin Temel Özellikleri)

Kitabın bu parçasında C++11 ile gelen taşıma semantiği konusunun şablonlar ile alakalı olmayan temel özellikleri incelenmiştir. Burada yer alan özellikler Modern C++ kullanıcılarının günlük her kod yazma işinde kullanabilecekleri özelliklerdir.

Bölüm 1: The Power of Move Semantics (Taşıma Semantiğinin Gücü)

Bu bölümde öncelikle taşıma semantiği ile ilgili bir motivasyon girişi yapılmış, taşıma semantiği dile eklenmeden önce (C++03) ve eklendikten sonra (C++11) yazılan iki kod örneği birbirleriyle karşılaştırılmıştır. Taşıma semantiğinin kopyalama yapılan nesneler üzerindeki maliyeti nasıl azalttığından bahsedilmiştir. Açık ve kapalı yapılan taşıma işlemlerine değinilmiş, "std::move()" fonksiyon şablonu ele alınmıştır. Bununla birlikte Rvalue referans (sağ taraf referansı) kavramı açıklanmaya çalışılmış ("std::string&&" gibi), Copy Constructor ve Move Constructor’dan kısaca bahsedilmiştir.

Bölümün ilerleyen kısımlarında ise taşınan nesnenin durumunun ne olacağı üzerinde durulmuştur. Rvalue referans işlemenin tanımlanmadığı durumlarda kopyalama işleminin nasıl kullanıldığı açıklanmıştır. "const" olan nesneler üzerinde "std::move()" çağırmanın neden anlamsız olduğu açıklanmıştır. Son olarak da fonksiyonların geri dönüş türleri hakkında konuşulmuştur.

Bölüm 2: Core Features of Move Semantics (Taşıma Semantiğinin Ana Özellikleri)

Bu bölüm aslında ilk bölümde üzerinden geçilen konuların daha geniş anlatımını kapsamaktadır. Bazıları bir önceki bölümde bahsedilen şu konular üzerinde durulmuştur:Bu bölüm aslında ilk bölümde üzerinden geçilen konuların daha geniş anlatımını kapsamaktadır. Bazıları bir önceki bölümde bahsedilen şu konular üzerinde durulmuştur:

  • Rvalue referanslar ve Rvalue referans parametre alan fonksiyonlar
  • “std::move()” kullanımı, “std::move()” şablonunun hangi başlık dosyasında yer aldığı ve onun iç implementasyonu
  • Taşınan nesnelere tam olarak ne olduğu
  • Bir fonksiyonun farklı referans parametreleri ile aşırı yüklenmesi (overloading)
  • “const” Rvalue referansların kullanımı
  • Fonksiyona değer ile geçme ile Rvalue referans ile geçme arasındaki farklar

Bölüm 3: Move Semantics in Classes (Sınıflarda Taşıma Semantiği)

Bu bölümde anlatılan konular şunlardır:

  • Taşıma semantiğinin sıradan sınıflarda kullanımı
  • Özel kopyalama/taşıma üye fonksiyonlarının implementasyonu
  • Özel üye fonksiyonlar için bazı kurallar (özel üye fonksiyonların kullanılmasına veya kullanılmamasına göre oluşan senaryoların tek tek incelenmesi)
  • The Rule of Five ve The Rule of Three gibi kuralların ne anlama geldiği

Bölüm 4: How to Benefit From Move Semantics (Taşıma Semantiğinden Nasıl Faydalanılır)

Bu bölümde taşıma semantiğinin şu durumlarından bahsedilmiş ve onlarla ilgili örnekler verilmiştir:

  • İsimli nesnelerin kullanılmasını engellemesi
  • Gereksiz “std::move()” kullanımından kaçınmak
  • Sınıf üyelerini taşıma semantiği ile ilklendirmek (initialization)
  • Sınıf hiyerarşilerinde (türetme vb.) taşıma semantiğinin kullanımı

Bölüm 5: Overloading on Reference Qualifiers (Referans Niteleyicilerinde Aşırı Yükleme)

Bu bölümde öncelikle sınıflardan değer geri döndüren fonksiyonların farklı türlerdeki geri dönüş değerleri ele alnmış ve referans niteleyicileri konusuna giriş yapılmıştır. Sınıflardaki fonksiyonların referans niteleyicileri ile aşırı yüklenmesi (overloading) anlatılmaya çalışılmış, Rvalue referans niteleyicisi de örneklerle ele alınmıştır. Son olarak ise referans niteleyicilerinin hangi durumlarda kullanılması gerektiği açıklanmıştır.:

Bölüm 6: Moved-From States (Taşınmışlık Durumu)

Bu bölümde genel olarak taşınmış olan nesnelerin durumları tartışılmıştır. Taşınmış nesnelerin garanti edilen (guaranteed) ve gereken (required) durumları anlatılmaya çalışılmıştır. Taşınmış olan nesnelerin temel gereksinimleri karşılayıp karşılamadığından nasıl emin olacağımız, kırılan değişmezler (invariants) ile nasıl başa çıkacağımız senaryo senaryo incelenerek açıklanmıştır.

Bölüm 7: Move Semantics and noexcept (Taşıma Semantiği ve noexcept)

Bu bölümde genel olarak "noexcept" anahtar kelimesinin kullanımına ve taşıma semantiği ile arasındaki ilişkiye yer verilmiştir. Öncelikle "noexcept" alarak ve almadan yazılan Move Constructor’lar arasındaki farklar ele alınmıştır. Daha sonra "noexcept" bildirimlerin detaylarına girilmiştir. Farklı fonksiyon tiplerinde "noexcept" kullanımı örneklerle açıklanmıştır. En son ise "noexcept" anahtar kelimesinin nerede ve ne zaman kullanılabileceği anlatılmaya çalışılmıştır.

Bölüm 8: Value Categories (Değer Kategorileri)

Bu bölümde Modern C++’ın önemli konularından biri olan değer kategorileri (value categories) ve onların taşıma semantiği ile ilişkisi ele alınmıştır. C++’ta yer alan değer kategorileri açıklanmış ve onların özel kurallarına yer verilmiştir. Referansları bağlarken değer kategorilerinin önemi ele alınmıştır. Lvalue değerlerin ne zaman Rvalue haline geldiği ve Rvalue değerlerin ne zaman Lvalue haline geldiği anlatılmıştır. En son ise "decltype" ile değer kategorilerini kontrol etme tekniği anlatılmıştır.

Parça 2: Move Semantics in Generic Code (Genelleyici Kodlarda Taşıma Semantiği)

Bu parçada C++’ın genelleyici programlama (generic programming) araçları olan şablonlar (templates) ile taşıma semantiği arasındaki ilişkiler ve özellikler ele alınmaktadır.

Bölüm 9: Perfect Forwarding (Mükemmel Yönlendirme)

Bu bölümde öncelikle C++’ta mükemmel yönlendirme (perfect forwarding) tekniği ile ilgili genel bilgiler verilmiştir. Daha sonra evrensel (veya yönlendirici) referanslar anlatılmış ve "std::forward()" fonksiyon şablonu ile mükemmel yönlendirmenin nasıl yapılabileceği anlatılmıştır. Evrensel referanslar ile Rvalue referanslar arasındaki farklar ele alınmış, evrensel referanslar ile yapılan fonksiyon aşırı yüklemeleri anlatılmıştır. Son olarak ise Lambda fonksiyonlarında evrensel referans kullanımı örneklerle açıklanmıştır.

Bölüm 10: Tricky Details of Perfect Forwarding (Mükemmel Yönlendirmenin Zorlu Detayları)

Bu bölüm genel olarak mükemmel yönlendirmenin detayları ile ilgilidir. Bölümde anlatılan konuları şu şekilde sıralayabiliriz:

  • “const” olan ve olmayan nesneleri, onların “const” olma/olmama özelliklerini kaybetmeden evrensel referanslara bağlama
  • “std::forward()” kullanmadan bile evrensel referanslar kullanarak, taşıma semantiği ile geçilen argümanlar için özel yakalamalar yapmak
  • Şablonlardaki Rvalue referans parametreleri ile normal fonksiyonlardaki Rvalue referans parametrelerinin karşılaştırılması
  • Evrensel referansların, evrensel referanslıktan çıkma durumlarının tartışılması
  • “evrensel (universal)” ve “yönlendirici (forwarding)” referans terimlerinin nereden geldiği ve aralarındaki farkların tartışılması

Bölüm 11: Perfect Passing with auto&& (auto&& ile Mükemmel Geçiş)

Bu bölümde "auto&&" kullanımı ele elınmıştır. "auto&&" ile evrensel referanslar arasındaki ilişkiler, yönlendirici olmayan referanslar ile "auto&&" kullanımı, Lambda fonksiyonlarda mükemmel yönlendirme yapma gibi konular anlatılmaya ve açıklanmaya çalışılmıştır. Son olarak da C++20 fonksiyon bildirimlerinde "auto&&" kullanımına yer verilmiştir.

Bölüm 12: Perfect Returning with decltype(auto) (decltype(auto) ile Mükemmel Geri Dönüş)

Bu bölümde "decltype(auto)" türünden geri dönüş değerine sahip fonksiyonlar incelenmiştir. Öncelikle bu konu mükemmel geri dönüş adı altında ele alınmış, daha sonra da "decltype(auto)" kullanımın ayrıntılarına girilmiştir. En son ise Lambda fonksiyonlar ile ilgili kullanımlardan bahsedilmiştir.

Parça 3: Move Semantics in the C++ Standard Library (C++ Standart Kütüphanesinde Taşıma Semantiği)

Bu parçaya kadar olan bütün bölümlerde, taşıma semantiğinin bu kitap yazıldığı zaman olan standartlara kadar neredeyse bütün özellikleri ele alınmıştır. Bu parçada ise C++ Standart Kütüphanesi’nde yer alan taşıma semantiği ile ilgili değişiklikler ve özel durumlara yer verilmiştir.

Bölüm 13: Move-Only Types (Sadece Taşınabilir Türler)

Bu bölümde sadece taşınabilen türlerin ne olduğu ve bu türleri nasıl oluşturabileceğimiz ele alınmıştır. Ayrıca sadece taşınabilen türlerin fonksiyonlara geçilmesi, fonksiyonlardan geri dönüşü ve taşınmışlık durumları anlatılmaya çalışılmıştır.

Bölüm 14: Moving Algorithms and Iterators (Taşıma Algoritmaları ve İteratörler)

Bu bölümde STL’de yer alan ve içsel olarak taşıma semantiğini kullanan şu algoritmalar anlatılmıştır:

  • std::move()
  • std::move_backward()
  • std::remove()
  • std::remove_if()
  • std::unique()

Ayrıca algoritmalarda kullanılan taşıma iteratörleri (move iterators) de incelenmiştir.

Bölüm 15: Move Semantics in Types of the C++ Standard Library (C++ Standart Kütüphanesinde Yer Alan Türlerde Taşıma Semantiği)

Kitabın son bölümü olan bu bölümde C++ Standart Kütüphanesi’nde yer alan taşıma semantiğinin göze çarpan uygulama alanları incelenmiştir. Bölümde incelenen taşıma semantiği konularını şu şekilde sıralayabiliriz:

  • String’ler için taşıma semantiği
  • Konteyner (container) türleri için taşıma semantiği
  • “std::pair” ve “std::optional” için taşıma semantiği
  • Akıllı göstericiler (smart pointers) için taşıma semantiği
  • IOStream’ler için taşıma semantiği
  • Multithreading için taşıma semantiği

Değerlendirme

Kitap oldukça sade ve anlaşılır bir dilde yazılmıştır. Örnekler güzel seçilmiş ve iş hayatında karşımıza çıkabilecek örneklerin kullanılmasına özen gösterilmiştir. Bu kitabın hedef kitlesi, hali hazırda C++ dilini bilen ve C++ ile programlama yapma konusunda çok zorluk çekmeyen kişilerdir diyebiliriz. Kitap oldukça niş ve C++11 standartları ile dile eklenen bir kavramı geniş bir şekilde açıklamaktadır. Ancak anlatım sadece C++11 standartları ile sınırlandırılmamış; C++14, C++17 ve hatta C++20 standartlarında taşıma semantiği ile alakalı bilgilere de yer verilmiştir. Sonuç olarak bu kitap gerçekten de piyasada taşıma semantiği konusuna has olarak bulabileceğiniz şu ana kadarki en kapsamlı kitaptır.

Kitap genel olarak 3 parçadan meydana gelmektedir. İlk parçada taşıma semantiği konusuna motivasyon olarak giriş yapılmış ve neden taşıma semantiğine ihtiyaç duyabileceğimiz tartışılmıştır. Bununla beraber taşıma semantiğinin bir nevi yapı taşı sayılan Rvalue referans kavramına da yer verilmiştir. Bu bölümde taşıma semantiğinin şablonlar (templates) ile kullanımlarına yer verilmemiş, şablon içermeyen kodlardaki uygulamaları anlatılmıştır. Taşınmış nesnelerin durumları, "noexcept" ve taşıma semantiği ilişkisi, değer kategorileri gibi konularla bölüm sonlandırılmıştır. Sadece bu bölüm bile taşıma semantiğinin önemli bir kısmını anlamanıza yardımcı olabilir.

İkinci parçada taşıma semantiğinin C++’ın genelleyici programlama (generic programming) araçları olan şablonlar ile kullanım senaryoları incelenmektedir. Burada her şeyden önce yönlendirici referans veya Scott Meyers’in tabiri ile evrensel referans (universal reference) olarak adlandırılan ve şablonlarda karşımıza çıkan bir referans türü incelenmektedir. Bu konu ayrıntıları ile açıklanıp uygulamaları gösterildikten sonra, mükemmel yönlendirme (perfect forwarding) isimli teknik açıklanmaktadır. Bunu takiben "auto&&" ve "decltype(auto)" ile taşıma semantiği arasındaki ilişkiler temiz bir şekilde incelenmektedir. Gerçekten de bu bölüm şablonlar ile programlama yapan kişiler için benzersiz bir bölümdür. Anlatımlar oldukça açıklayıcı ve örnekler oldukça gerçek kullanımlara yakındır.

Son parçada taşıma semantiğinin C++ Standart Kütüphanesi ile ilişkisi ve son standartlarda bu kütüphanede ne gibi değişikliklere yol açtığı anlatılmaya çalışılmıştır. Bu bölüm biraz kısa gibi gözükse de içeriği oldukça yeterlidir. C++ Standart Kütüphanesi’nde yer alan ve taşıma semantiği ile ilişkili algoritmaların açıklanmasının yanı sıra, kütüphanede yer alan çok çeşitli veri türü ve konteyner türlerinin C++ ile ilişkisi temel olarak incelenmektedir. Eğer bu bölüm çok ayrıntı ile açıklanacak olsaydı, kitap kapsamını aşabilir ve başka bir kitaba dönüşebilirdi. Bu nedenle bu parça aslında tam olması gereken uzunlukta bırakılmıştır.

Sonuç olarak, bu kitap hali hazırda C++ ile uğraşan ancak Modern C++ tarafına geçiş yapmak isteyen veya buradaki bilgilerini güçlendirmek isteyen kişiler için piyasada doğrudan taşıma semantiği ile ilgili bulabileceğiniz (şimdilik) tek kitaptır. Kitapta kullanılan dil oldukça anlaşılırdır, ancak C++ temelleri konusunda eksiklikleri olan kişiler için bazı yerler anlaşılmaz gelebilir. Bunun dışında kitapta çok fazla görsel kullanılmamıştır. Ancak birçok yerde de bence buna ihtiyaç yoktur. Yine de bazı yerlerde daha fazla diyagram, bölümü daha açıklayıcı hale getirebilirdi. Daha önce de belirttiğim gibi, kitap bu konu özelinde piyasada eşsizdir. İnternet üzerinde farklı kaynaklardan bilgileri birleştirerek ancak bu kitaptaki bilgilerin tamamını elde edebilirsiniz. Kitapta verilen örnekler ve analojiler yine oldukça yerinde ve açıklayıcıdır.

C++ Move Semantics – The Complete Guide İnceleme Özeti


Tam İsim: C++ Move Semantics – The Complete Guide
Basım No: 1st Edition
Yazarlar: Nicolai M. Josuttis
Yayımlama Tarihi: 30 Ağustos 2020
Sayfa Sayısı: 264
Anlaşılabilirlik/Okunabilirlik
Görsel/Diyagram Kullanımı
İçerik Kalitesi/Eşsizliği
Örneklendirme/Örnek Kalitesi

Sonuç Özeti

Sonuç olarak, bu kitap hali hazırda C++ ile uğraşan ancak Modern C++ tarafına geçiş yapmak isteyen veya buradaki bilgilerini güçlendirmek isteyen kişiler için piyasada doğrudan taşıma semantiği ile ilgili bulabileceğiniz (şimdilik) tek kitaptır. Kitapta kullanılan dil oldukça anlaşılırdır, ancak C++ temelleri konusunda eksiklikleri olan kişiler için bazı yerler anlaşılmaz gelebilir. Bunun dışında kitapta çok fazla görsel kullanılmamıştır. Ancak birçok yerde de bence buna ihtiyaç yoktur. Yine de bazı yerlerde daha fazla diyagram, bölümü daha açıklayıcı hale getirebilirdi. Daha önce de belirttiğim gibi, kitap bu konu özelinde piyasada eşsizdir. İnternet üzerinde farklı kaynaklardan bilgileri birleştirerek ancak bu kitaptaki bilgilerin tamamını elde edebilirsiniz. Kitapta verilen örnekler ve analojiler yine oldukça yerinde ve açıklayıcıdır.

4.5
0 0 votes
Article Rating
Subscribe
Bildir
guest

0 Yorum
Inline Feedbacks
View all comments