Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

copy elision visible side effect

Consider this code:

#include <iostream>

using namespace std;

struct Foo {
public:
    int _a{};
    Foo(int a) : _a{a} 
    {
        std::cout << "ctor" << std::endl;
    }

    Foo(const Foo &)
    {
        std::cout << "copy" << std::endl;
    }
};

int main () {
    Foo a{10};
    Foo b = 10;
    std::cout << b._a << std::endl;
}

When I compile with

g++ -std=c++11 -fno-elide-constructors test.cpp

the output is

ctor ctor copy 0

which is what I expect, since the in Foo b = 10, 10 is implicitly constructed from int, then b is copy constructed from Foo. Furthermore, my copy constructor doesn't do anything, so the member _a remains 0 (as it is in-class-initialized).

However, when I use copy elision

g++ -std=c++11 test.cpp

the output is

ctor ctor 10

which is surprising to say the least. I understand that the copy constructor is elided here, but this is a serious side-effect (the fact that the member is once initialized to 0 and once to 10), as it affects the rest of the code path.

Is this behaviour normal?

like image 960
vsoftco Avatar asked Sep 18 '25 11:09

vsoftco


1 Answers

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);
like image 69
Dietmar Kühl Avatar answered Sep 20 '25 23:09

Dietmar Kühl