C++ Copy Constructor и Exceptions Handling

Ниже приведен очень простой пример того как работает copy constructor:

class Base
{
  public:
    Base() { std::cout << "Base default constructor invoked!" << std::endl; };
    Base(const Base& copy) { std::cout << "Base copy constructor invoked!" << std::endl; };
    Base& operator=(const Base& copy) = default;
};

class Derived : public Base
{
  public:
    Derived() { std::cout << "Derived default constructor invoked!" << std::endl; }
    Derived(const Derived& copy) { std::cout << "Derived copy constuctor invoked!" << std::endl; }
};

int main(void)
{
   Derived der;
   Derived der0 = der;

   return 0;
}

И если в функции main изменить Derived der0, на Derived& der0, то copy constructor не будет вызван.

Отсюда появляется вопрос, почему когда мы отлавливаем исключения по ссылке:

try
{
   // throw error
} 
catch(std::exception& e) {}

Тогда у нас будет вызван конструктор копирования и при этом только для класса exception? Почему в обычной ситуации у нас (как в примере выше) не вызывается никакой конструктор копирования для класса Base когда мы выполняем Derived& der0 = der, но в блоке catch он вызывается, при этом только для исключения самого верхнего уровня?

Пример того как это работает, но без объяснения нашел здесь.


Ответы (1 шт):

Автор решения: AlexGlebe

  На ссылке, что вы скинули рассматривается передача аргументов по значению и по ссылке на константный объект. В вашем примере вы показываете ссылку на действительный (имеющий адрес) объект (не константный). Ваш пример не такой.
  Аргументы функций вида const & принимают объекты любого типа (на временные или действительные). К конструктору копирования не имеют никакого отношения.

void f(int const & x) {
  ... }

void h(int & x) {
  ... }

void g(void){
  int x = 10 ;
  f(x); // Ok
  h(x); // Ok
  f(int(7.5)); // Ok

  h(int(7.5)); 
  // error: cannot bind non-const lvalue reference of type ‘int&’ to an rvalue of type ‘int’

  }
→ Ссылка