Sobes.tech
Middle+

Какво знаете за гаранциите за сигурност на изключенията?

sobes.tech AI

Отговор от AI

Гарантиите за безопасност на изключенията определят поведението на функцията при възникване на изключение. Различават се четири нива на гаранции:

  1. Базова гаранция (Basic guarantee): Ако функцията хвърли изключение, програмата остава в валидно състояние. Ресурсите не се губят (например, паметта се освобождава), но точната стойност на обектите може да е неизвестна. Възможно е да продължите да работите с приложението.

    // Пример за базова гаранция
    void basic_guarantee_function(std::vector<int>& vec, int value) {
        // Могат да възникнат изключения при вмъкване
        vec.push_back(value); 
        // Ако възникне изключение, vec може да бъде в непредсказуемо състояние (частично променено),
        // но паметта, заделена за vec, ще бъде коректно освободена при изход от обхвата.
    } 
    
  2. Строга гаранция (Strong guarantee): Ако функцията хвърли изключение, състоянието на програмата остава същото като преди извикването. Всички промени се отменят.

    // Пример за строга гаранция
    // Използваме идиома Copy-and-Swap за осигуряване на строга гаранция
    class Resource {
        int* data;
        size_t size;
    public:
        Resource(size_t s) : size(s), data(new int[s]) {}
        ~Resource() { delete[] data; }
        Resource(const Resource& other) : size(other.size), data(new int[other.size]) {
            std::copy(other.data, other.data + size, data); // Може да хвърли изключение
        }
        Resource& operator=(Resource other) // Прехвърляне по стойност
        {
            swap(*this, other); // Не хвърля изключения
            return *this;
        }
        friend void swap(Resource& first, Resource& second) noexcept {
            using std::swap;
            swap(first.data, second.data);
            swap(first.size, second.size);
        }
        // ... други членове
    };
    
    void strong_guarantee_function(Resource& res, size_t new_size) {
        Resource temp(new_size); // Ако тук възникне изключение, res няма да се промени
        res = temp;               // Използваме пренатоварения оператор =, който осигурява строга гаранция
    }
    
  3. Гаранция без изключения (No-throw guarantee): Функцията гарантирано не хвърля изключения. Такива функции се означават със спецификатора noexcept.

    // Пример без изключения
    void no_throw_function() noexcept {
        // Няма операции, които могат да хвърлят изключение
        int a = 5;
        int b = 10;
        int c = a + b;
    }
    
  4. Гаранция за неуспех (Failure guarantee): В контекста на безопасността на изключенията, понякога се споменава този ниво, което означава, че функцията може да остави програмата в неопределено състояние, възможно с изтичане на ресурси или грешки. Това е практически липса на гаранции. Такова поведение трябва да се избягва.

Значението на гаранциите за безопасност на изключенията е в създаването на надежден и предсказуем код, който правилно обработва грешките и управлението на ресурсите дори при възникване на изключения. Изборът на ниво на гаранция зависи от критичността на операцията, разходите за връщане и вероятността за възникване на изключение.

Таблица за сравнение на гаранциите:

Гаранция Състояние при изключение Цялостност на данните Изтичане на ресурси
Базова Валидна, но неопределена Не е гарантирано Не
Строга Не се променя (като преди извикването) Запазва се Не
Без изключения Никога не се случва (няма изключения) N/A N/A
Неуспех (липса) Неопределена, възможно повреждане или грешки Не е гарантирано Възможно