mercredi 22 novembre 2023

How to prevent copy elision when implementing custom array functionality? [closed]

I'm writing a class CValue in C++, which is supposed to be an analog of values in JavaScript. CValue object can be almost every type, depending on initialization/assignment: primitive value (bool, int, double, string objects, etc.), array, or even an object (a hash map with property names as keys and CValue as values). All work just fine, but I have some troubles with arrays and object element access. I will explain the problem for arrays.

To access elements of an array, CValue has the following method:

CValue CValue::operator[](int index)

Notice, that I return CValue, not CValue& - that is because the object on which this operator was called may not be an array. In that case I just return empty CValue, which is like undefined from JS. When I call operator[] on a valid array value and given index is correct, then I return a reference-like CValue object, which contains a pointer to actually stored element in the array under the hood. This value is not a copy of original array element, because I want to be able to change it like so:

arr[0] = 42;

If I were returning a copy of array element, then, obviously, I would change its copy, not the original element.

So I only need to return reference-like CValue objects when I access elements of arrays (or objects). In other scenarios I just make a copy of another value. For example:

CValue var1 = 42;
CValue var2 = var1;  // var1 = 42, var2 = 42
var2 = 100;          // var1 = 42, var2 = 100

And now, finally, I can describe the problem to you. When I write

CValue var = arr[0];

compiler thinks, that it is a great opportunity for him to use copy elision, and instead of using copy constructor (which will make a copy of value) it just replaces newly created value with reference-like CValue object, returned from operator[]. This leads to following unwanted behaviour:

arr[0] = 42;
CValue var = arr[0];  // var = 42,  arr[0] = 42
var = 100;            // var = 100, arr[0] = 100

I can use variable var to fully access first element of arr. But I just wanted to make a copy of it. So my question is:

How can I prevent copy elision here to avoid this unwanted begaviour?

NOTE: I know I can disable it completely in compiler flags, but I don't want to do this, because copy elision is quite useful overall.

Aucun commentaire:

Enregistrer un commentaire