попробуй поймать в C ++ - сколько объектов создано - PullRequest
0 голосов
/ 12 мая 2018

Рассмотрим следующий код:

#include <iostream>
#include <string>
class Box{
    public: 
        std::string show(){
            std::cout<<"Box show executed"<<std::endl;
            return "msg";
        };

        ~Box(){
            std::cout<<"Box destructor is executed"<<std::endl;
        };
};

int main(){

    try{
        Box obj;
        std::cout<<"Coming here"<<std::endl;
        throw obj;
    }
    catch(Box msg){
        std::cout<<"I have caught the exception: \n"<<msg.show()<<std::endl;
    }

}

В компиляторе GCC вывод:

Coming here
Box destructor is executed
Box show executed
I have caught the exception:
msg
Box destructor is executed
Box destructor is executed

Мои заблуждения:

  1. Печатные издания заявления очень запутанные, почему "Box show" выполнил "печать перед строкой" Я поймал исключение "?

  2. Называется три деструктора. Как это возможно, когда только создаются два объекта, один объект Box в try и временный объект в try, который передается в блок catch?

Ответы [ 3 ]

0 голосов
/ 12 мая 2018

почему печать "Box show execute" печатается перед строкой "Я поймал исключение"?

Поскольку он хочет оценить метод show() в разделе catch,сначала будет напечатана строка.

Есть три деструктора с именем

Поскольку вы обычно перехватываете Box, если вы используете Box&, вы увидите только 2 вызовадеструктору.В вашем коде объект копируется дважды, и с 1 основным объектом вам нужно 3 вызова деструктора.Если вы измените свой код следующим образом, вы увидите следующие конструкторы копирования:

#include <iostream>
#include <string>
class Box{
    public: 
        Box(){}
        Box(const Box &obj){
            std::cout <<"copy"<<std::endl;
        }

        std::string show(){
            std::cout<<"Box show executed"<<std::endl;
            return "msg";
        };

        ~Box(){
            std::cout<<"Box destructor is executed"<<std::endl;
        };
};

int main(){

    try{
        Box obj;
        std::cout<<"Coming here"<<std::endl;
        throw obj;
    }
    catch(Box msg){
        std::cout<<"I have caught the exception: \n"<<msg.show()<<std::endl;
    }    
}

, и результат будет:

Coming here
copy                          // <-- for throw
Box destructor is executed
copy                          // <-- when you catch at catch(Box msg)
Box show executed
I have caught the exception: 
msg
Box destructor is executed
Box destructor is executed

Для чего нужны эти copy?один для throw obj;, а другой для catch(Box msg).

0 голосов
/ 12 мая 2018

Я думаю, это поможет вам следить за тем, что происходит, если вы добавите конструктор и скопируете конструктор в свой код.

#include <iostream>
#include <string>
class Box {
public:
    std::string show() {
        std::cout << "Box show executed - " << this << std::endl;
        return "msg";
    };

    Box() {
        std::cout << "Box constructor is executed " << this << std::endl;
    }

    Box(const Box& rhs) {
        std::cout << "Box copy constructor is executed " << this << std::endl;
    }

    ~Box() {
        std::cout << "Box destructor is executed " << this << std::endl;
    };
};

int main() {

    try {
        Box obj;
        std::cout << "Coming here" << std::endl;
        throw obj;
    }
    catch (Box msg) {
        std::cout << "I have caught the exception: \n" << msg.show() << std::endl;
    }

}

Это дает следующий вывод:

/*
Box constructor is executed 0051FB0B 
Coming here 
Box copy constructor is executed 0051FA33
Box copy constructor is executed 0051FAFF 
Box destructor is executed 0051FB0B 
Box show executed - 0051FAFF 
I have caught the exception: msg 
Box destructor is executed 0051FAFF 
Box destructor is executed 0051FA33
*/

Таким образом, вы можете видеть ответ на # 1 в том, что два новых объекта создаются во время броска и улова. Сразу после этого исходный объект разрушается, поскольку теперь он находится вне области видимости блока.

Следующая часть немного сбивает с толку, потому что есть два вложенных оператора std :: cout. В этом случае компилятор решил полностью разрешить выражение msg.show () до того, как произвел вывод для первой части строки «Я поймал исключение ...». Таким образом, поскольку он разрешал значение для msg.show (), msg.show () сначала выдало свою собственную строку вывода «Box show .....», поэтому она появилась первой. Как С.М. В его ответе указывается, что порядок, в котором компилятор выбирает оценку вложенного std :: cout, определяется реализацией, и этот порядок операций не гарантируется.

Наконец, объект, созданный в catch, уничтожается, а затем объект, созданный в результате попытки, уничтожается.

0 голосов
/ 12 мая 2018

Распечатки операторов очень запутаны, почему печать "Box show выполняется" перед строкой "Я поймал исключение"?

Порядок вычисления функции / операторааргументы не уточняются.Ваш код эквивалентен следующему:

operator<<(operator<<((std::cout << "I have caught the exception: \n"), msg.show()), std::endl);

Какой из двух приведенных ниже выполняется первым, не определен:

std::cout << "I have caught the exception: \n"
msg.show() // i.e. std::cout << "Box show executed" << std::endl;

В вашем случае msg.show() вычисляется перед первым operator << называется.Другой компилятор может создавать код с этими вызовами в другом порядке.

Вызывается три деструктора. Как это возможно, когда создаются только два объекта, один объект Box в try и tempобъект в попытке, который передается в блок catch?

Когда вы бросаете локальный объект по значению:

  1. Он копируется в специальную зарезервированную память для исключений.
  2. Исходный объект уничтожен (1).
  3. Должен быть найден обработчик исключения, и объект скопирован из специальной зарезервированной памяти в стек обработчика исключений.
  4. Скопированный объектудаляется из специальной памяти (2).
  5. При выходе из обработчика исключений объект удаляется из его стека (3).
...