Elisiyani nusxalash - Copy elision - Wikipedia

Yilda C ++ kompyuter dasturlash, nusxa ko'chirish a ga ishora qiladi kompilyatorni optimallashtirish keraksizlarni yo'q qiladigan texnika ob'ektlarni nusxalash. C ++ til standarti, odatda, dasturning kuzatiladigan xatti-harakatlari bir xil bo'lishi sharti bilan, har qanday optimallashtirishni amalga oshirishga imkon beradi go'yo, ya'ni o'zini ko'rsatib, dastur standart talablariga muvofiq bajarilgan.

Standart, shuningdek, dasturning xatti-harakatlarini o'zgartiradigan bo'lsa ham nusxalashni yo'q qilish mumkin bo'lgan bir nechta vaziyatlarni tavsiflaydi, eng keng tarqalgani qaytish qiymatini optimallashtirishdir. Da tasvirlangan yana bir keng qo'llaniladigan optimallashtirish C ++ standarti, qachon bo'lsa a vaqtinchalik ob'ekt ning sinf turi bir xil turdagi ob'ektga ko'chiriladi.[1] Natijada, nusxalash-boshlash odatda tengdir to'g'ridan-to'g'ri boshlash ishlash jihatidan, ammo semantikada emas; nusxalash-boshlash hali ham talab qiladi kirish mumkin nusxa ko'chirish konstruktori.[2] Optimallashtirish vaqtincha mos yozuvlar bilan bog'langan ob'ektga tatbiq etilishi mumkin emas.

Misol

# shu jumladan <iostream>int n = 0;tuzilmaviy C {  aniq C(int) {}  C(konst C&) { ++n; }  // nusxa konstruktori ko'rinadigan yon ta'sirga ega};                      // u ob'ektni statik saqlash muddati bilan o'zgartiradiint asosiy() {  C c1(42);      // to'g'ridan-to'g'ri ishga tushirish, C :: C-ni chaqiradi (42)  C c2 = C(42);  // nusxa ko'chirish-boshlash, qo'ng'iroqlar C :: C (C (42))  std::cout << n << std::endl;  // agar nusxa berilgan bo'lsa 0 ni, aks holda 1 ni bosib chiqaradi}

Standartga muvofiq, shunga o'xshash optimallashtirish mavjud ob'ektlarga nisbatan qo'llanilishi mumkin tashlangan va ushlangan,[3][4] ammo optimallashtirish tashlangan ob'ektdan to ikkala nusxaga tegishli bo'ladimi-yo'qmi noma'lum istisno ob'ekti, va nusxasi istisno ob'ekti da e'lon qilingan ob'ektga istisno-deklaratsiya ning ushlash bandi. Ushbu optimallashtirish faqat tegishli bo'ladimi, aniq emas vaqtinchalik narsalar, yoki nomlangan narsalar ham.[5] Quyidagi manba kodi berilgan:

# shu jumladan <iostream>tuzilmaviy C {  C() = sukut bo'yicha;  C(konst C&) { std::cout << "Salom Dunyo! n"; }};bekor f() {  C v;  otish v;  // nomlangan ob'ektni istisno ob'ektiga nusxalash.}  // Ushbu nusxa berilishi (chiqarilishi) mumkinmi yoki yo'qmi noma'lum.int asosiy() {  harakat qilib ko'ring {    f();  } ushlamoq (C v) {  // istisno ob'ektini vaqtincha ichiga nusxalash                   // istisno deklaratsiyasi.  }  // Ushbu nusxa berilishi (qoldirilishi) mumkinmi yoki yo'qmi, ham aniq emas.}

Muvofiq kompilyator shuning uchun a ishlab chiqarishi kerak dastur qaysi "Dunyoga salom!" ikki marta. C ++ standartining joriy tahririda (C ++ 11 ), masalalar ko'rib chiqildi, bu asosan nomlangan ob'ektdan istisno ob'ektiga nusxasini va istisno ishlovchilarida e'lon qilingan ob'ektga nusxasini olish imkonini beradi.[5]

GCC beradi Nofno-elide ‑ konstruktorlari nusxa ko'chirishni o'chirib qo'yish opsiyasi. Ushbu parametr, qaytish qiymatini optimallashtirish yoki nusxalari berilgan boshqa optimallashtirish ta'sirini kuzatish (yoki kuzatmaslik) uchun foydalidir. Odatda ushbu muhim optimallashtirishni o'chirib qo'yish tavsiya etilmaydi.

Qaytish qiymatini optimallashtirish

Kontekstida C ++ dasturlash tili, qaytish qiymatini optimallashtirish (RVO) a kompilyatorni optimallashtirish yo'q qilishni o'z ichiga oladi vaqtinchalik ob'ekt ushlab turish uchun yaratilgan funktsiya qaytish qiymati.[6] RVO, natijada kuzatiladigan xulq-atvorni o'zgartirishga ruxsat berilishi bilan ajralib turadi dastur tomonidan C ++ standarti.[7]

Xulosa

Umuman olganda, C ++ standarti kompilyator Natijada har qanday optimallashtirishni amalga oshirish bajariladigan bir xil kuzatiladigan xatti-harakatlarni namoyish etadi go'yo (ya'ni o'zini ko'rsatib berish) standartning barcha talablari bajarildi. Bu odatda "deb nomlanadigo'yo qoida ".[8] Atama qaytish qiymatini optimallashtirish dagi maxsus bandga ishora qiladi C ++ standarti bu "go'yo" qoidasidan ham kattaroq: dastur a natijasida kelib chiqqan nusxalash operatsiyasini o'tkazib yuborishi mumkin qaytarish bayonoti, bo'lsa ham nusxa ko'chirish konstruktori bor yon effektlar.[1]

Quyidagi misol, agar nusxa ko'chirish konstruktori ko'rinadigan yon ta'sirga ega bo'lsa ham (matni bosib chiqarish), amalga oshirilayotgan nusxalardan birini yoki ikkalasini yo'q qilishi mumkin bo'lgan stsenariyni namoyish etadi.[1] Yo'q qilinishi mumkin bo'lgan birinchi nusxa - bu nomsiz vaqtinchalik nusxa C funktsiyaga ko'chirilishi mumkin f"s qaytish qiymati. Yo'q qilinishi mumkin bo'lgan ikkinchi nusxa - bu vaqtinchalik ob'ektning nusxasi f ga obj.

# shu jumladan <iostream>tuzilmaviy C {  C() = sukut bo'yicha;  C(konst C&) { std::cout << "Nusxasi olingan. n"; }};C f() {  qaytish C();}int asosiy() {  std::cout << "Salom Dunyo! n";  C obj = f();}

Ga qarab kompilyator va bu kompilyatorning sozlamalari, natijada dastur quyidagi natijalardan birini namoyish qilishi mumkin:

Salom Dunyo! Nusxasi olingan va nusxasi olingan.
Salom Dunyo! Nusxasi olingan.
Salom Dunyo!

Fon

Ob'ektni qaytarish o'rnatilgan turi dan funktsiya odatda ortiqcha yuklarni ko'taradi, chunki ob'ekt odatda a ga to'g'ri keladi CPU registri. Ning kattaroq ob'ektini qaytarish sinf turi bir xotira joyidan boshqasiga qimmatroq nusxalashni talab qilishi mumkin. Bunga yo'l qo'ymaslik uchun dastur qo'ng'iroq qiluvchida yashirin ob'ektni yaratishi mumkin suyakka ramkasi, va ushbu ob'ekt manzilini funktsiyaga o'tkazing. Keyin funktsiyani qaytarish qiymati yashirin ob'ektga ko'chiriladi.[9] Shunday qilib, quyidagi kabi kod:

tuzilmaviy Ma'lumotlar {   char bayt[16]; };Ma'lumotlar F() {  Ma'lumotlar natija = {};  // natija yaratish  qaytish natija;}int asosiy() {  Ma'lumotlar d = F();}

bunga teng kod yaratishi mumkin:

tuzilmaviy Ma'lumotlar {  char bayt[16];};Ma'lumotlar* F(Ma'lumotlar* _hiddenAddress) {  Ma'lumotlar natija = {};  // natijani yashirin ob'ektga nusxalash  *_hiddenAddress = natija;  qaytish _hiddenAddress;}int asosiy() {  Ma'lumotlar _ yashirin;           // yashirin ob'ekt yaratish  Ma'lumotlar d = *F(&_ yashirin);  // natijani d ga nusxalash}

bu sabab bo'ladi Ma'lumotlar nusxa ko'chirish kerak bo'lgan ob'ekt.

Evolyutsiyasining dastlabki bosqichlarida C ++, tilning ob'ektini samarali ravishda qaytarib bera olmasligi sinf turi funktsiyadan zaiflik deb hisoblangan.[10] Taxminan 1991 yil, Uolter Yorqin nusxa ko'chirishni minimallashtirish uchun texnikani amalga oshirdi, natijada maxfiy ob'ektni va funktsiyadagi nomlangan ob'ektni natijani ushlab turish uchun foydalaniladigan ob'ekt bilan samarali ravishda almashtirdi:[11]

tuzilmaviy Ma'lumotlar {  char bayt[16];};bekor F(Ma'lumotlar* p) {  // to'g'ridan-to'g'ri * p natijasini yarating}int asosiy() {  Ma'lumotlar d;  F(&d);}

Yorqin ushbu optimallashtirishni o'zida qo'llagan Zortech C ++ kompilyator.[10] Keyinchalik ushbu maxsus uslub "nomlangan qaytish qiymatini optimallashtirish" deb nomlangan bo'lib, bu nomlangan ob'ektni nusxalash zarurligini anglatadi.[11]

Tuzuvchini qo'llab-quvvatlash

Qaytish qiymatini optimallashtirish ko'plab kompilyatorlarda qo'llab-quvvatlanadi.[6][12][13] Ammo kompilyator optimallashtirishni amalga oshirolmaydigan holatlar bo'lishi mumkin. Umumiy holatlardan biri shundaki, funktsiya bajarilish yo'liga qarab har xil nomlangan ob'ektlarni qaytarishi mumkin:[9][12][14]

# shu jumladan <string>std::mag'lubiyat F(bool kond = yolg'on) {  std::mag'lubiyat birinchi("birinchi");  std::mag'lubiyat ikkinchi("ikkinchi");  // funktsiya nomlangan ikkita ob'ektdan birini qaytarishi mumkin  // uning argumentiga qarab. RVO qo'llanilmasligi mumkin  qaytish kond ? birinchi : ikkinchi;}int asosiy() {  std::mag'lubiyat natija = F();}

Tashqi havolalar

Adabiyotlar

  1. ^ a b v ISO /IEC (2003). ISO / IEC 14882: 2003 (E): dasturlash tillari - C ++ §12.8 Sinf ob'ektlarini nusxalash [class.copy] paragraf. 15
  2. ^ Sutter, o't (2001). Ko'proq istisno C ++. Addison-Uesli.
  3. ^ ISO /IEC (2003). ISO / IEC 14882: 2003 (E): dasturlash tillari - C ++ §15.1 Istisno holatini tashlash [bundan mustasno] paragraf. 5
  4. ^ ISO /IEC (2003). ISO / IEC 14882: 2003 (E): dasturlash tillari - C ++ §15.3 Istisno bilan ishlash [bundan mustasno]. paragraf. 17
  5. ^ a b "C ++ standart tilidagi nuqsonlar to'g'risida hisobotlar". WG21. Olingan 2009-03-27.
  6. ^ a b Meyers, Skott (1995). Keyinchalik samarali C ++. Addison-Uesli.
  7. ^ Aleksandresku, Andrey (2003-02-01). "Konstruktorlarni ko'chirish". Doktor Dobbning jurnali. Olingan 2009-03-25.
  8. ^ ISO /IEC (2003). ISO / IEC 14882: 2003 (E): dasturlash tillari - C ++ §1.9 Dasturning bajarilishi [intro.execution] paragraf. 1
  9. ^ a b Bulka, Dov; Devid Mayhew (2000). Samarali C ++. Addison-Uesli. ISBN  0-201-37950-3.
  10. ^ a b Lippman, Sten (2004-02-03). "Ismni qaytarish qiymatini optimallashtirish". Microsoft. Olingan 2009-03-23.
  11. ^ a b "Lug'at D dasturlash tili 2.0". Raqamli Mars. Olingan 2009-03-23.
  12. ^ a b Shoukry, Ayman B. (2005 yil oktyabr). "Visual C ++ 2005 da nomlangan qaytish qiymatini optimallashtirish". Microsoft. Olingan 2009-03-20.
  13. ^ "C ++ dialektini boshqarish parametrlari". GCC. 2001-03-17. Olingan 2018-01-20.
  14. ^ Xinnant, Xovard; va boshq. (2002-09-10). "N1377: C ++ tiliga ko'chirish semantikasini qo'llab-quvvatlashni taklif qilish". WG21. Olingan 2009-03-25.