Пример для проверки вызовов конструкторов копирования и деструкторов при передаче параметров и возврате значений из функции.


// file elide.cpp

#include 

/*
    Проверка вызовов конструктора копирования при 
    передаче параметров в функцию и при возвращении значения.
    Тестовый класс с печатью в своих методах значения х 
    и указателя на класс (чтобы понимать у кого это было)
*/

class A
{
   int x;
public:
   A(int xx=0) : x(xx) { 
      printf("main constructor %p.A(%d)\n",(void*)this,x); 
   }
   A(const A & a) : x(a.x) { 
      printf("copy constructor %p.A(%p)\n",(void*)this, (void*)&a); 
   }
  ~A() {
      printf("destructor %p\n",(void*)this);
   }
   const A & operator=(const A &a) { 
      x = a.x; 
      printf("%p.x = %p.x;\n", (void*)this, (void*)&a); 
      return * this; 
   }
};

A fun(A aa) {        // конструктор A(aa) параметра процедуры
//A fun(const A &aa) {      // сравните что будет с таким заголовком
    A r(aa);         // создание внутреннего объекта r
    return r;        // конструктор возвращаемого значения A(r)
}                    // деструктор параметра, 

int main()
{
    A a(1),  c;
    printf("----------------\n");
    c = fun(a);
    printf("----------------\n");
    printf("the end\n");
    return 0;
}

/*
  компиляция
  g++ elide.cpp -fno-elide-constructors

  после выполнения получится что-то такое
main constructor 000000000061fe04.A(1)   - конструкторы объектов а и с
main constructor 000000000061fe00.A(0)
----------------
copy constructor 000000000061fe0c.A(000000000061fe04)  - конструктор передачи параметра аа
copy constructor 000000000061fdcc.A(000000000061fe0c)  - конструктор внутреннего объекта r
copy constructor 000000000061fe08.A(000000000061fdcc)  - конструктор возвращаемого значения
destructor 000000000061fdcc                  - деструктор врутреннего объекта r (функция завершилсь)
000000000061fe00.x = 000000000061fe08.x;     - возвращаемое значение пошло в правую часть присваивания
destructor 000000000061fe08                  - деструктор правой части (присваивание завершилось)
destructor 000000000061fe0c                  - деструктор параметра функции
----------------
the end
destructor 000000000061fe00       - деструкторы объектов  а и с
destructor 000000000061fe04

А теперь умный компилятор уберет лишние конструкторы
  компиляция
  g++ elide.cpp 

  после выполнения получаем
main constructor 000000000061fe04.A(1)  - то же самое
main constructor 000000000061fe00.A(0)
----------------
copy constructor 000000000061fe0c.A(000000000061fe04)  - параметр функции aa
copy constructor 000000000061fe08.A(000000000061fe0c)  - сразу возвращаемое значение !!!
000000000061fe00.x = 000000000061fe08.x;               - и в правую часть присваивания его
destructor 000000000061fe08                            - деструктор правой части присваивания
destructor 000000000061fe0c                            - деструктор параметра функции aa
----------------
the end
destructor 000000000061fe00
destructor 000000000061fe04

*/