4

Say we have a struct that has a member pointer that conditionally points to either an internal array, or to somewhere on the heap, like this:

struct Ex {
        char* p;
        char data[14];
        bool is_heap;
        Ex() : p(&data[0]), data(), is_heap(false) {}
        //etc...
};

Now consider this function

Ex f1() {return Ex();}

Due to copy elision, the following code will print out "h":

int main() {
        auto ex = f1();
        ex.data[0] = 'h';
        std::cout << ex.p[0];
}

But, consider the following function

Ex f2() {
        auto ret = Ex();
        return ret;
}

As far as I am aware, this function may be elided, but if it's not, the following code will be undefined behavior:

int main() {
        auto ex = f2();
        ex.data[0] = 'h';
        std::cout << ex.p[0]; // maybe derefrencing dangling pointer, maybe printing out "h"?
}

My question is, is example 2 always undefined behavior? Is it up to the compiler whether it is undefined behavior (as in if it decided to elide or not)? or is it well defined behavior? (same questions may also apply to the first example)

Jake Schmidt
  • 1,558
  • 9
  • 16

1 Answers1

4

In all cases where copy-elision is not mandatory, you have undefined behavior when you do:

auto ex = ... 
ex.data[0] = 'h';
std::cout << ex.p[0]; 

From c++17, this function:

Ex f1() {return Ex();}

is guaranteed to do copy-elision, so the above code is fine if ex is the result of f1().

In general, I recommend not relying on this, and simply providing the correct copy-constructor for your class to avoid such issues.

cigien
  • 57,834
  • 11
  • 73
  • 112