Yazılım Geliştirme: C ++ 17 ile özel tahsisatçılar

Adanali

Active member
Yazılım Geliştirme: C ++ 17 ile özel tahsisatçılar


  1. Yazılım Geliştirme: C ++ 17 ile özel tahsisatçılar

Son makalem “Yazılım Geliştirme: C ++ 17 ile Polimorfik Tahsisatçı” C ++ 17'de polimorfik tahsis teorisini sundum. Bugün teoriyi kullanacağım.










Rainer Grimm yıllardır yazılım mimarı, ekip ve eğitim müdürü olarak çalıştı. C ++ programlama dilleri, Python ve Haskell hakkında makaleler yazmayı seviyor, ancak uzman konferanslarla konuşmayı da seviyor. Modern C ++ blogunda, C ++ tutkusuyla yoğun bir şekilde ilgileniyor.







Devam etmeden önce, son makalemin en önemli bölümleri bile “Yazılım Geliştirme: C ++ 17 ile Polimorfik Tahsisat”.

Kısa Hafıza


Aşağıdaki program polimorfik tahsisler kullanır:



// polymorphicAllocator.cpp

#include <array>
#include <cstddef>
#include <memory_resource>
#include <vector>

int main() {

std::array<std::byte, 200> buf1; // (1)
std::pmr::monotonic_buffer_resource pool1{buf1.data(),
buf1.size()};
std::pmr::vector<int> myVec1{&pool1}; // (3)
for (int i = 0; i < 5; ++i) {
myVec1.push_back(i);
}

char buf2[200] = {}; // (2)
std::pmr::monotonic_buffer_resource pool2{std::data(buf2),
std::size(buf2)};
std::pmr::vector<int> myVec2{&pool2};
for (int i = 0; i < 200; ++i) {
myVec2.push_back(i);
}

}


Şimdi kalkmak istiyorum myVec2 odak. 200 intS. std::pmr::vector<int> itti. Bu 200 intS bire uyum sağlamaz char buf[200] Ve bu yüzden atlıyor std::pmr::new_delete_resource() Söylediği gibi -yukarı akışta ve küresel new elementlerin geri kalanı için. Şimdi Alkator'dan yukarı akıştan yararlanacağım.

İzleme tahsisi




Aşağıdaki program bir öncekine dayanmaktadır, bir izleme tahsisatı kullanır ve dinamik bellek atamasını ve sürümünü görünür hale getirir.



// trackAllocator.cpp

#include <array>
#include <cstdlib>
#include <format>
#include <iostream>
#include <memory_resource>
#include <vector>

class TrackAllocator : public std::pmr::memory_resource {
void* do_allocate(std::size_t bytes,
std::size_t alignment) override {
void* p = std::pmr::new_delete_resource()->
allocate(bytes, alignment);
std::cout <<
std::format(" do_allocate: {:6} bytes at {}n",
bytes, p);
return p;
}

void do_deallocate(void* p,
std::size_t bytes,
std::size_t alignment) override {
std::cout <<
std::format(" do_deallocate: {:4} bytes at {}n",
bytes, p);
return
std::pmr::new_delete_resource()->
deallocate(p, bytes, alignment);
}

bool do_is_equal(const std::pmr::memory_resource& other)
const noexcept override {
return std::pmr::new_delete_resource()->is_equal(other);
}
};


int main() {

std::cout << 'n';

TrackAllocator trackAllocator; // (1)
std::pmr::set_default_resource(&trackAllocator); // (2)

std::cout << "myVec1n";

std::array<std::byte, 200> buf1;
std::pmr::monotonic_buffer_resource pool1{buf1.data(),
buf1.size()};
std::pmr::vector<int> myVec1{&pool1}; // (3)
for (int i = 0; i < 5; ++i) {
myVec1.push_back(i);
}

std::cout << "myVec2n";

char buf2[200] = {};
std::pmr::monotonic_buffer_resource pool2{std::data(buf2),
std::size(buf2)};
std::pmr::vector<int> myVec2{&pool2}; // (4)
for (int i = 0; i < 200; ++i) {
myVec2.push_back(i);
}

std::cout << 'n';

}


TrackAllocator Depolama tahsisini ve onayını izlemek için bir Alkator. Arayüz sınıfı tarafından yönetilir std::pmr::memory_resource tüm depolama kaynaklarının türettiği. TrackAllocator Talep edilen üyelerin üç işlevini tanımlar do_allocate,, do_deallocate VE do_is_equal. Her çağrı bunu çağrıya götürür std::pmr::new_delete_resource daha öte. std:pmr::new_delete_resource Standart depolama kaynağıdır ve küresel olarak adlandırılır new VE delete AÇIK. Üye işlevinin görevi do_is_equal İki depolama kaynağının aynı olup olmadığını kontrol etmektir. Örneği kullanan ilginç nokta, belleğin üyenin işlevlerinde atadığım ve yayınladığımdır. do_allocate VE do_deallocate görüş.






C ++ 20 ile tanıtılan kavramlar, modern C ++ uygulamalarının oluşturulmasını kütüphane, modüller ve aralıkların aralıkları ile yeniden tanımladı. İtibaren 7. 9 Kasım 2023'e kadar Rainer Grimm'i yoğun C ++ 20 laboratuvarına getiriyor: Yeni kavramlar, C ++ 20 Porta'nın birçok yararlı işlevini açıklıyor ve tam olarak yanıtlıyor.







Aniden TrackAllocator (Satır 1) ve onu standart bir kaynak haline getirin (2). myVec1 (3) e myVec2 (4) Yukarı akışlı bir tahsisatçı olarak kullanın. Bu alakator, birincil inokatör tüketildiğinde müdahale eder. Bu geri dönüş için myVec1 için gerekli değil myVec2 Ama zaten.

Bu baskı, dinamik ödevi ve onayını göstermektedir. myVec2Değin std::pmr::vector<int> Tüm intS kaydedebilir.









Yukarı akış bir tahsisatçı da belirli bir kapa bağlanabilir.

Allokatif olmayan bir alakator


std::pmr::null_resource_allocator Özel bir Alkator. Bunları tahsis etmek için kullanmak std::bad_alloc-İstisna. Bu depolama kaynağı, belleğin yığın üzerine tahsis etmemenizi garanti eder:



// nullMemoryResource.cpp

#include <array>
#include <cstddef>
#include <iostream>
#include <memory_resource>
#include <string>
#include <vector>

int main() {

std::cout << 'n';

std::array<std::byte, 2000> buf;
std::pmr::monotonic_buffer_resource pool{buf.data(),
buf.size(), // (1)
std::pmr::null_memory_resource()};
std::pmr::vector<std::pmr::string> myVec{&pool}; // (2)
try {
for (int i = 0; i < 100; ++i) { // (3)
std::cerr << i << " ";
myVec.emplace_back("A short string");
}
}
catch (const std::bad_alloc& e) { // (4)
std::cerr << 'n' << e.what() << 'n';
}

std::cout << 'n';

}


İlk olarak, yığın üzerindeki belleği kontrol edin ve başlatın std::pmr::monotonic_buffer_resource onunla. Ardından bu depolama kaynağını kullanın e std::pmr::null_memory_resource Bir tahsisatçı olarak yukarı akış (1). (2) içinde bir tane yaratıyorum std::pmr::vector<std::pmr::string>. Bir tane olduğum için std::pmr::string Dizeyi kullanın, depolama kaynağını ve yukarı akış tahsisatını da kullanın. Eğer ben std::pmr::vector<std::string> ABD, ABD std::string Global Tahsisler new VE delete. Sonunda (3) 100 telinde bir tane oluşturuyorum ve (4) 'de bir tane alıyorum std::bad_alloc-Aksption. Hak ettiği şeye sahibim: 100 tel bire uyum sağlamıyor std::array<std::byte, 2000>-Tampon. 17 telden sonra sürüntü kullanılır.









Sırada ne var?


. std::pmr::monotonic_buffer Mükemmel özelliklere sahiptir. Oldukça hızlıdır ve bir bellek bırakmaz. Bir sonraki makalem numaralar sağlıyor.


(RME)
 
Üst