Yazılım Geliştirme: Std :: C ++ 20'de SPAN: Daha fazla ayrıntı

Adanali

Active member
Yazılım Geliştirme: Std :: C ++ 20'de SPAN: Daha fazla ayrıntı


  1. Yazılım Geliştirme: Std :: C ++ 20'de SPAN: Daha fazla ayrıntı

Bugün çok iyi bilinmeyen özellikler hakkında bir tane görmek istiyorum std::span Ve tehlikeleri yazın. Ayrıca araştırma için kişisel bir endişe ile ilgilidir.










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.













A std::spanBazen Vista olarak adlandırılır, asla bir sahip değildir. Bu tutarlı bellek basit bir dizi, belirli bir boyutta bir işaretçi olabilir, std::array, A std::vector oa std::string Olmak. Tipik bir uygulama, ilk öğesine ve boyutuna bir işaretçiden oluşur. Birinin ana nedeni std::span<T> IS: Bir C dizisi, bir işleve teslim edildiğinde ilk öğesinde bir işaretçiye indirgenir. Bu, dizinin boyutunu kaybetti. Bu çürüme, C/C ++ hatalarının tipik bir nedenidir.

Otomatik olarak belirlenen boyut


Aksine, kurşun std::span<T> Nesnelerin tutarlı sonuçlarının boyutu otomatik olarak.


// printSpan.cpp&#13;
&#13;
#include <iostream>&#13;
#include <vector>&#13;
#include <array>&#13;
#include <span>&#13;
&#13;
void printMe(std::span<int> container) {&#13;
&#13;
std::cout << "container.size(): " << container.size() << 'n'; // (4)&#13;
for(auto e : container) std::cout << e << ' ';&#13;
std::cout << "nn";&#13;
}&#13;
&#13;
int main() {&#13;
&#13;
std::cout << std::endl;&#13;
&#13;
int arr[]{1, 2, 3, 4}; // (1)&#13;
printMe(arr);&#13;
&#13;
std::vector vec{1, 2, 3, 4, 5}; // (2)&#13;
printMe(vec);&#13;
&#13;
std::array arr2{1, 2, 3, 4, 5, 6}; // (3)&#13;
printMe(arr2);&#13;
&#13;
}


Craray C (1), std::vector (2) Ve bu std::array (3) Sadece intSonuç olarak görüntüleyin std::span Ayrıca intS. Bu basit örnekte hala ilginç bir şey var. Her kap için yapabilir std::span Boyutunu türetir (4).











Bu kısa bir anıydı std::span. Geri kalan her şey önceki makalemde “C ++ 20: STD :: span ile nesne dizilerine Gußer erişim”.

Bir std :: span statik bir uzantıya veya dinamik bir uzantıya sahip olabilir.

Dinamiklere karşı statik uzantı


Varsayılan olarak var std::span dinamik bir uzantı:


template <typename T, std::size_t Extent = std::dynamic_extent>&#13;
class span;


Eğer std::span Statik bir uzantıya sahiptir, boyutları derleme süresi ve veri türünün bir kısmı ile bilinir: std::span. Bu nedenle, uygulamanın nesnelerin tutarlı bölümünün ilk öğesine sadece bir işaretçiye ihtiyacı vardır.

Bir std::span Dinamik bir uzantı ile, bir işaretçi ilk öğeden ve tutarlı nesne dizisinin boyutundan oluşur. Boyut bir parçası değil std::span-Uç.

Bir sonraki örnek, iki tür açıklık arasındaki farkları göstermektedir.


// staticDynamicExtentSpan.cpp&#13;
&#13;
#include <iostream>&#13;
#include <span>&#13;
#include <vector>&#13;
&#13;
void printMe(std::span<int> container) { // (3) &#13;
&#13;
std::cout << "container.size(): " << container.size() << 'n';&#13;
for (auto e : container) std::cout << e << ' ';&#13;
std::cout << "nn";&#13;
}&#13;
&#13;
int main() {&#13;
&#13;
std::cout << 'n';&#13;
&#13;
std::vector myVec1{1, 2, 3, 4, 5}; &#13;
std::vector myVec2{6, 7, 8, 9};&#13;
&#13;
std::span<int> dynamicSpan(myVec1); // (1)&#13;
std::span<int, 4> staticSpan(myVec2); // (2)&#13;
&#13;
printMe(dynamicSpan);&#13;
printMe(staticSpan);&#13;
&#13;
// staticSpan = dynamicSpan; ERROR // (4)&#13;
dynamicSpan = staticSpan; // (5) &#13;
&#13;
printMe(staticSpan); // (6)&#13;
&#13;
std::cout << 'n';&#13;
&#13;
}


dynamicSpan (1) dinamik bir uzantısı var staticSpan (2) Bir statik var. İkisi birden std::spanBoyutlarını işlevde verin printMe (3) Geri. A std::span Statik uzantı ile yapabilirsiniz std::span Dinamik uzantı ile atanabilir, ancak tam tersi değil. (4) Bir hataya neden olur, ancak (5) ve (6) geçerlidir.









Özel bir uygulaması var std::span. A std::span Değişen elemanların sabit bir alanı olabilir.

Değişen öğelerin sabit bir alanı


Basitlik nedeniyle bir tane arıyorum std::vector ve bir std::span Alan. A std::vector Değişen Değişen Elemanları Modeller: std::vector. Eğer yaparsan std::vector GİBİ const Bildirildi, sabit nesnelerin sabit bir alanını modelledi: const std::vector. Değişen elemanların sabit bir alanını modellemek mümkün değildir. Bu noktada geliyor std::span tehlikede. A std::span Değişen nesnelerin sabit bir alanı modelleri: std::span. Aşağıdaki şekilde, alanlar (sabit/değiştirme) ve elemanlar (sabit/değiştirme) arasındaki farkları göstermektedir.









// constRangeModifiableElements.cpp&#13;
&#13;
#include <iostream>&#13;
#include <span>&#13;
#include <vector>&#13;
&#13;
void printMe(std::span<int> container) {&#13;
&#13;
std::cout << "container.size(): " << container.size() << 'n'; &#13;
for (auto e : container) std::cout << e << ' ';&#13;
std::cout << "nn";&#13;
}&#13;
&#13;
int main() {&#13;
&#13;
std::cout << 'n';&#13;
&#13;
std::vector<int> origVec{1, 2, 2, 4, 5};&#13;
&#13;
// Modifiable range of modifiable elements&#13;
std::vector<int> dynamVec = origVec; // (1)&#13;
dynamVec[2] = 3;&#13;
dynamVec.push_back(6);&#13;
printMe(dynamVec);&#13;
&#13;
// Constant range of constant elements&#13;
const std::vector<int> constVec = origVec; // (2)&#13;
// constVec[2] = 3; ERROR&#13;
// constVec.push_back(6); ERROR&#13;
std::span<const int> constSpan(origVec); // (3)&#13;
// constSpan[2] = 3; ERROR&#13;
&#13;
// Constant range of modifiable elements&#13;
std::span<int> dynamSpan{origVec}; // (4)&#13;
dynamSpan[2] = 3;&#13;
printMe(dynamSpan);&#13;
&#13;
std::cout << 'n';&#13;
&#13;
}


Taşıyıcı dynamVec (1) Değişen elemanlara sahip değişen bir alandır. Bu ifade taşıyıcı için geçerli değildir constVec (2). constVec Elemanlarını veya boyutunu değiştiremez. constSpan (3) Buna göre davranır. dynamSpan (4) Değişen elementlerle sabit bir alanın benzersiz uygulamasını modeller.

Son olarak, kullanılan iki tehlikenin altını çizmek istiyorum std::span Bilmeli.

Std :: span tehlikeleri


Tipik sorunları std::span Onlar iki şey. Her şeyden önce bir std::span Geçici bir alana uygulanmazlar; İkincisi, altta yatan tutarlı alanın boyutu std::span Değişmediler.

A std::spaN geçici bir alanda


A std::span Asla bir sahip değildir ve aşağıdaki alanın süresini uzatmaz. O zaman bir std::span Yalnızca lvalues üzerinde çalışır. Bir kullanımı std::span Belirsiz davranış geçici bir alanda bulunur.


// temporarySpan.cpp&#13;
&#13;
#include <iostream>&#13;
#include <span>&#13;
#include <vector>&#13;
&#13;
std::vector<int> getVector() { // (2)&#13;
return {1, 2, 3, 4, 5};&#13;
}&#13;
&#13;
int main() {&#13;
&#13;
std::cout << 'n';&#13;
&#13;
std::vector<int> myVec{1, 2, 3, 4, 5}; // (1)&#13;
std::span<int, 5> mySpan1{myVec}; &#13;
std::span<int, 5> mySpan2{getVector().begin(), 5}; // (3)&#13;
&#13;
for (auto v: std::span{myVec}) std::cout << v << " ";&#13;
std::cout << 'n';&#13;
for (auto v: std::span{getVector().begin(), 5}) std::cout << v << " "; // (4)&#13;
&#13;
std::cout << "nn";&#13;
&#13;
}


Bir kullanımı std::span Statik bir uzantı veya std::span Lvalue üzerinde dinamik bir uzatma ile sorun değil. Lvalue'den geldiğimde std::vector (1) içinde geçici bir std::vector işlev yoluyla değişim getVector (2) Oluşturulur, programın belirsiz davranışları vardır. Hem (3) hem de (4) geçerli değildir. Yürütme sırasında belirsiz davranış görünür hale gelir. (4) 'deki çıktı ile doğru değil std::vector İşlevinkini birleştirin getVector() Yaratılmıştır.









Altta yatan tutarlı alanın boyutunu değiştirin

Altta yatan tutarlı alanın boyutunu değiştirirseniz, tutarlı alan yeniden -Aalocata ve std::span Eski verileri ifade eder.


std::vector<int> myVec{1, 2, 3, 4, 5};&#13;
&#13;
std::span<int> sp1{myVec};&#13;
&#13;
myVec.push_back(6); // undefined behavior


Sırada ne var?


Bir sonraki makalemde kendimi C ++ 20 Biçimlendirme Kütüphanesine daldırıyorum.

Araştırma için bağış toplama kampanyamız










3 kitaplık modern C ++ paket koleksiyonum artık fiyatın yarısında mevcuttur (70 $-> 35 $). SLA'da arama yapmak için parayı vereceğim. Gerçeklerle başlamak istiyorum.

Çok Alt Çocukluk Üzerine Araştırma


İşte ALS polikliniğinin bir açıklaması:

Sanki tıbbın “sorunlu çocuklarından” biri – nadir hastalıklar sosyal olarak odaklanmamıştı. SLA üzerinde araştırma konusunda genel bir finansman yoktur. Bu nedenle, insanların tedavisi önemli ölçüde alt yüzerdir. Bağışlar ve dış destek büyük önem taşımaktadır.

Bu alt analyzing, kovanın buz için meydan okumasından anlaşıldı.

Araştırmanın daha fazla paraya ihtiyacı var. İşte benim fikrim. Bir bağış toplama başlatalım!

Bağış Toplama Kampanyamız


C ++ Modern Bundle 3-Kitap Koleksiyonu için kupon fiyatın yarısı (70 $-> 35 $) 21 Ocak'a (dahil) kadar geçerlidir.

Aşağıdaki üç kitap bu pakete dahil edilmiştir: C ++ Standart Kütüphanesi, Modern C ++ ve C ++ 20 ile rekabet.

Tüm parayı ALS polikliniğine bağışlayacağım. ALS polikliniği Charité'nin bir parçasıdır ve Avrupa'daki AR'nin araştırma ve tedavisinde liderdir.


(RME)
 
Üst