Sobes.tech
Middle+

Hərəkət semantikası nədir və onu necə istifadə etmək olar?

sobes.tech Süni İntellekt

AI-dan cavab

Hərəkət semantikasını (move semantics) C++11 və yuxarı versiyalarda effektiv resursların idarə olunması üçün imkan verir, bu da lazımsız kopyalamadan qaçmağa kömək edir. Bu, rvalue istinadları (&&) və std::move operatorundan istifadə etməklə həyata keçirilir.

Əsas aspektlər:

  • rvalue istinadları (&&): Müvəqqəti obyektlərə (yəni, rvalues) və ya köçürülə bilən obyektlərə istinadlar. Tezliklə məhv ediləcək obyektə bağlanmağa imkan verir.
  • std::move operatoru: Lvalue-i rvalue istinadına çevirir. Öz-özlüyündə köçürmə əməliyyatı etmir, sadəcə kompilyatora obyektin təhlükəsiz şəkildə köçürülə biləcəyini bildirir.
  • Köçürmə konstrukturu: rvalue istinadını arqument kimi qəbul edən xüsusi konstruktur. O, resursları (məsələn, dinamik yaddaş göstəriciləri) mənbə obyektindən oğurlayır və onu etibarlı, lakin boş vəziyyətə salır.
  • Köçürmə ilə təyin operatoru: Köçürmə konstrukturu kimi, təyin əməliyyatları üçün nəzərdə tutulub.

İstifadə:

  1. Təkmilləşdirmə: Böyük obyektlərin və ya resurslara sahib obyektlərin (məsələn, konteynerlər, sətirlər, ağıllı göstəricilər) kopyalanma xərclərini azaldır.
  2. Effektiv konteynerlərin tətbiqi: std::vector kimi konteynerlərin ölçüsünü dəyişərkən və ya köçürərkən effektiv idarə etməyə imkan verir.
  3. Böyük obyektlərin dəyər kimi geri qaytarılması: Kompilyator avtomatik olaraq köçürmə tətbiq edə bilər (return value optimization, RVO və ya Named Return Values Optimization, NRVO), əgər geri qaytarılan obyekt yerli dəyişən və ya müvəqqəti obyekt olarsa.

Nümunə:

#include <iostream>
#include <vector>
#include <string>
#include <utility> // std::move üçün

class MyResource {
public:
    std::vector<int> data;

    // Konstruktor
    MyResource(size_t size) : data(size) {
        std::cout << "Konstruktor" << std::endl;
    }

    // Destructor
    ~MyResource() {
        std::cout << "Destructor" << std::endl;
    }

    // Köçürmə konstrukturu
    MyResource(MyResource&& other) noexcept : data(std::move(other.data)) {
        std::cout << "Köçürmə konstrukturu" << std::endl;
    }

    // Köçürmə operatoru
    MyResource& operator=(MyResource&& other) noexcept {
        if (this != &other) {
            data = std::move(other.data);
        }
        std::cout << "Köçürmə operatoru" << std::endl;
        return *this;
    }
};

int main() {
    MyResource res1(10); // Konstruktor
    std::cout << "---" << std::endl;
    MyResource res2 = res1; // Kopyalama konstrukturu və ya kopyalama operatoru, əgər res2 artıq mövcuddursa
    std::cout << "---" << std::endl;
    MyResource res3 = std::move(res1); // Köçürmə konstrukturu
    std::cout << "---" << std::endl;
    MyResource res4(5); // Konstruktor
    res4 = std::move(res3); // Köçürmə operatoru
    std::cout << "---" << std::endl;

    return 0;
}

Bu nümunədə, std::move istifadə edilərək, köçürmə konstrukturu və ya köçürmə operatoru çağırılır, bu da data vektorunun məzmununun bahalı kopyalanmasının qarşısını alır.