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