Уничтожение возвращаемого объекта - PullRequest
3 голосов
/ 20 апреля 2020

Я читал подраздел 18.2. Конструкторы и деструкторы раздела 18, обработка исключений в C ++ 17, стандартный черновик , где есть пример (стр. 384). Я пытался понять, где происходит уничтожение объекта A, возвращенного внутри блока try, но не смог найти. Поэтому я скопировал пример, добавил несколько отпечатков и увидел, что dtor этого объекта никогда не вызывается. Что мне здесь не хватает? Кто-нибудь, пожалуйста, объясните, что здесь происходит.

#include <stdio.h>

struct A {
    int a_;
    explicit A(int a):a_(a) {
        printf("A(%d)'s ctor\n", a_);
    }
    ~A() {
        printf("A(%d)'s dtor\n", a_);
    }
};

struct Y { ~Y() noexcept(false) {
    printf("y's dtor\n");
    throw 0; } };

A f() {
    try {
        A a(23);
        Y y;
        A b(56);
        return A(100); // #1 who destructs this ??
    } catch (...) {
        printf("handling exception..\n");
    }
    printf("At line %d now..\n", __LINE__);
    return A(200); // #2
}

int main() {
    auto ret = f();
    printf("f returned A(%d) object\n", ret.a_);
    return 0;
}

Над кодом выводится следующее:

A(23)'s ctor                                                                                                                                                  
A(56)'s ctor                                                                                                                                                  
A(100)'s ctor                                                                                                                                                 
A(56)'s dtor                                                                                                                                                  
y's dtor                                                                                                                                                      
A(23)'s dtor                                                                                                                                                  
handling exception..                                                                                                                                          
At line 34 now..                                                                                                                                              
A(200)'s ctor                                                                                                                                                 
f returned A(200) object                                                                                                                                      
A(200)'s dtor                                                                                                                                                 


...Program finished with exit code 0

Ответы [ 2 ]

4 голосов
/ 20 апреля 2020

В соответствии со стандартом C ++ 17 [исключением.ктор] / 2:

Если при уничтожении временных или локальных переменных для оператора return генерируется исключение, деструктор для возвращаемый объект (если есть) также вызывается. Объекты уничтожаются в порядке, обратном завершению их построения.

Затем приведен иллюстративный пример (который вы немного изменили) для демонстрации: после броска деструктора Y следующая вещь случается так, что объект A(100) должен быть уничтожен, поэтому вы должны увидеть сообщение об уничтожении.

Опубликованный вывод указывает на ошибку компилятора. Это очень похоже на проблему, о которой сообщается как ошибка LLVM 12286 и g cc ошибка 33799 .

Последняя помечена как исправленная в G CC 10 (после первоначального сообщения в 2007 году!). Тем не менее, тестирование с версией 10.0.1 20200418 (experimental) на Godbolt : даже если контрольный пример в отчете об ошибке 33799 исправлен, код в этом вопросе остается незафиксированным. Я добавил комментарий к этому сообщению об этом примере.

0 голосов
/ 20 апреля 2020

Обычно вызывающая функция ответственна за уничтожение возвращаемого значения функции, но точные детали являются частью ABI платформы C ++.

В большинстве ABI, вызывая функцию, которая возвращает нетривиальный Значение (все, что не помещается в регистр или, возможно, два), выполняется путем передачи скрытого дополнительного аргумента, указывающего, где должно быть построено возвращаемое значение. Вызывающая сторона выделяет пространство в своем кадре для возвращаемого значения и передает указатель на это пространство.

...