For a struct
with const
members
struct point { const int x; const int y; };
that is used as member data
struct Foo
{
point pt{ 0, 0 };
void move_x(int value);
};
How can Foo::move_x()
be written to update Foo::pt
? Is it OK to use memcpy()
?
#include <memory.h>
void Foo::move_x(int value)
{
const point pt_{ pt.x + value, pt.y };
(void) memcpy(&pt, &pt_, sizeof(pt_)); // pt = pt_;
}
This can be safely done using a pointer
#include <memory>
struct Bar
{
std::unique_ptr<point> pPt_{ new point{ 0, 0 } };
const point& pt() const {
return *pPt_;
}
void move_x(int value) {
pPt_.reset(new point{ pt().x + value, pt().y });
}
};
but the point
is then always stored on the heap rather than in Bar
.
Note that clients don't really care about point
at all:
Foo foo;
foo.move_x(314); // (314, 0)
Bar bar;
bar.move_x(3141); // (3141, 0)
A variable, const or not, is just a location in memory, and you can break the rules of const and simply overwrite it.
You can const individual members of a struct. Declaring an entire instance of a struct with a const qualifier is the same as creating a special-purpose copy of the struct with all members specified as const .
This is clearly undefined behavior. Now, "can" this be done? Sure, it can, but only in the sense that the compiler will not complain. But one aspect of C++ is just because the compiler doesn't complain it doesn't mean that the resulting code will work right.
It's only a matter of time before someone writes some code that reads pt
, calls move_x()
, and then reads pt
again.
A modern, optimizing compiler will rightfully assume that because the code is reading const
instances, their values cannot change, and then proceed and optimize away the second read from pt
, using the data cached from the first read of pt
, in the CPU registers.
And then, the hapless programmer will spend a week trying to figure out why the code is clearly not doing what the program says it should be doing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With