Consider this code:
#include
using namespace std;
struct Foo {
public:
int _a{};
Foo(int a) : _a{a}
{
std::cout <<
The whole point of singling copy elision out as a on optimization in specific cases is to allow eliding side effects of copy construction. That is, yes, it expected that copy elision happens despite the copy constructor and/or the destructor having side effects.
If you don't want copy elision to happen in certain cases you'll need to arrange for it to be inhibited. In your specific case it is admittedly a bit annoying to inhibit copy elision but something like this should do the trick:
template <typename T>
T const& inhibit(T const& ref) {
return ref;
}
// ...
Foo b = inhibit<Foo>(10);